Update LVGL to v9.1.0
@@ -1,2 +1,3 @@
|
||||
*.out
|
||||
*_Runner.c
|
||||
*.bin
|
||||
@@ -6,276 +6,126 @@ if(ESP_PLATFORM)
|
||||
|
||||
else()
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(lvgl_tests LANGUAGES C)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(lvgl_tests LANGUAGES C CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
|
||||
set(FLAG_CHECK_WHITELIST --coverage -fsanitize=address -Werror)
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckCXXCompilerFlag)
|
||||
function(filter_compiler_options lang options_out)
|
||||
set(options ${ARGN})
|
||||
foreach(option ${options})
|
||||
if (option IN_LIST FLAG_CHECK_WHITELIST)
|
||||
list(APPEND ${options_out} ${option})
|
||||
continue()
|
||||
endif ()
|
||||
|
||||
string(TOUPPER FLAG_SUPPORTED_FOR_${lang}_${option} option_var_name)
|
||||
string(REPLACE "-" "_" option_var_name ${option_var_name})
|
||||
|
||||
if (${lang} STREQUAL C)
|
||||
check_c_compiler_flag(${option} ${option_var_name})
|
||||
elseif (${lang} STREQUAL CXX)
|
||||
check_cxx_compiler_flag(${option} ${option_var_name})
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown language ${lang}")
|
||||
endif ()
|
||||
if(${option_var_name})
|
||||
list(APPEND ${options_out} ${option})
|
||||
endif()
|
||||
endforeach()
|
||||
set(${options_out} ${${options_out}} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
find_program(VALGRIND_EXECUTABLE valgrind)
|
||||
if (VALGRIND_EXECUTABLE)
|
||||
set(MEMORYCHECK_COMMAND ${VALGRIND_EXECUTABLE})
|
||||
set(MEMORYCHECK_COMMAND_OPTIONS --error-exitcode=1)
|
||||
endif()
|
||||
|
||||
include(CTest)
|
||||
|
||||
set(LVGL_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
set(LVGL_TEST_COMMON_EXAMPLE_OPTIONS
|
||||
-DLV_BUILD_EXAMPLES=1
|
||||
-DLV_USE_DEMO_WIDGETS=1
|
||||
-DLV_USE_DEMO_STRESS=1
|
||||
|
||||
set(LVGL_TEST_OPTIONS_VG_LITE
|
||||
-DLV_TEST_OPTION=6
|
||||
)
|
||||
|
||||
set(LVGL_TEST_OPTIONS_MINIMAL_MONOCHROME
|
||||
-DLV_COLOR_DEPTH=1
|
||||
-DLV_MEM_SIZE=65535
|
||||
-DLV_DPI_DEF=40
|
||||
-DLV_DRAW_COMPLEX=0
|
||||
-DLV_USE_METER=0
|
||||
-DLV_USE_LOG=1
|
||||
-DLV_USE_ASSERT_NULL=0
|
||||
-DLV_USE_ASSERT_MALLOC=0
|
||||
-DLV_USE_ASSERT_MEM_INTEGRITY=0
|
||||
-DLV_USE_ASSERT_OBJ=0
|
||||
-DLV_USE_ASSERT_STYLE=0
|
||||
-DLV_USE_USER_DATA=0
|
||||
-DLV_FONT_UNSCII_8=1
|
||||
-DLV_USE_BIDI=0
|
||||
-DLV_USE_ARABIC_PERSIAN_CHARS=0
|
||||
-DLV_BUILD_EXAMPLES=1
|
||||
-DLV_FONT_DEFAULT=&lv_font_montserrat_14
|
||||
-DLV_USE_PNG=1
|
||||
-DLV_USE_BMP=1
|
||||
-DLV_USE_GIF=1
|
||||
-DLV_USE_QRCODE=1
|
||||
-DLV_TEST_OPTION=1
|
||||
)
|
||||
|
||||
set(LVGL_TEST_OPTIONS_NORMAL_8BIT
|
||||
-DLV_COLOR_DEPTH=8
|
||||
-DLV_MEM_SIZE=65535
|
||||
-DLV_DPI_DEF=40
|
||||
-DLV_DRAW_COMPLEX=1
|
||||
-DLV_USE_LOG=1
|
||||
-DLV_USE_ASSERT_NULL=0
|
||||
-DLV_USE_ASSERT_MALLOC=0
|
||||
-DLV_USE_ASSERT_MEM_INTEGRITY=0
|
||||
-DLV_USE_ASSERT_OBJ=0
|
||||
-DLV_USE_ASSERT_STYLE=0
|
||||
-DLV_USE_USER_DATA=1
|
||||
-DLV_FONT_UNSCII_8=1
|
||||
-DLV_USE_FONT_SUBPX=1
|
||||
-DLV_USE_BIDI=0
|
||||
-DLV_USE_ARABIC_PERSIAN_CHARS=0
|
||||
${LVGL_TEST_COMMON_EXAMPLE_OPTIONS}
|
||||
-DLV_FONT_DEFAULT=&lv_font_montserrat_14
|
||||
-DLV_USE_PNG=1
|
||||
-DLV_USE_BMP=1
|
||||
-DLV_USE_SJPG=1
|
||||
-DLV_USE_GIF=1
|
||||
-DLV_USE_QRCODE=1
|
||||
-DLV_TEST_OPTION=2
|
||||
)
|
||||
|
||||
set(LVGL_TEST_OPTIONS_16BIT
|
||||
-DLV_COLOR_DEPTH=16
|
||||
-DLV_COLOR_16_SWAP=0
|
||||
-DLV_MEM_SIZE=65536
|
||||
-DLV_DPI_DEF=40
|
||||
-DLV_DRAW_COMPLEX=1
|
||||
-DLV_DITHER_GRADIENT=1
|
||||
-DLV_USE_LOG=1
|
||||
-DLV_USE_ASSERT_NULL=0
|
||||
-DLV_USE_ASSERT_MALLOC=0
|
||||
-DLV_USE_ASSERT_MEM_INTEGRITY=0
|
||||
-DLV_USE_ASSERT_OBJ=0
|
||||
-DLV_USE_ASSERT_STYLE=0
|
||||
-DLV_USE_USER_DATA=1
|
||||
-DLV_FONT_UNSCII_8=1
|
||||
-DLV_USE_FONT_SUBPX=1
|
||||
-DLV_USE_BIDI=0
|
||||
-DLV_USE_ARABIC_PERSIAN_CHARS=0
|
||||
${LVGL_TEST_COMMON_EXAMPLE_OPTIONS}
|
||||
-DLV_FONT_DEFAULT=&lv_font_montserrat_14
|
||||
-DLV_USE_PNG=1
|
||||
-DLV_USE_BMP=1
|
||||
-DLV_USE_SJPG=1
|
||||
-DLV_USE_GIF=1
|
||||
-DLV_USE_QRCODE=1
|
||||
-DLV_TEST_OPTION=3
|
||||
)
|
||||
|
||||
set(LVGL_TEST_OPTIONS_16BIT_SWAP
|
||||
-DLV_COLOR_DEPTH=16
|
||||
-DLV_COLOR_16_SWAP=1
|
||||
-DLV_MEM_SIZE=65536
|
||||
-DLV_DPI_DEF=40
|
||||
-DLV_DRAW_COMPLEX=1
|
||||
-DLV_DITHER_GRADIENT=1
|
||||
-DLV_DITHER_ERROR_DIFFUSION=1
|
||||
-DLV_GRAD_CACHE_DEF_SIZE=8*1024
|
||||
-DLV_USE_LOG=1
|
||||
-DLV_USE_ASSERT_NULL=0
|
||||
-DLV_USE_ASSERT_MALLOC=0
|
||||
-DLV_USE_ASSERT_MEM_INTEGRITY=0
|
||||
-DLV_USE_ASSERT_OBJ=0
|
||||
-DLV_USE_ASSERT_STYLE=0
|
||||
-DLV_USE_USER_DATA=1
|
||||
-DLV_FONT_UNSCII_8=1
|
||||
-DLV_USE_FONT_SUBPX=1
|
||||
-DLV_USE_BIDI=0
|
||||
-DLV_USE_ARABIC_PERSIAN_CHARS=0
|
||||
${LVGL_TEST_COMMON_EXAMPLE_OPTIONS}
|
||||
-DLV_FONT_DEFAULT=&lv_font_montserrat_14
|
||||
-DLV_USE_PNG=1
|
||||
-DLV_USE_BMP=1
|
||||
-DLV_USE_SJPG=1
|
||||
-DLV_USE_GIF=1
|
||||
-DLV_USE_QRCODE=1
|
||||
set(LVGL_TEST_OPTIONS_FULL_24BIT
|
||||
-DLV_TEST_OPTION=4
|
||||
)
|
||||
|
||||
set(LVGL_TEST_OPTIONS_FULL_32BIT
|
||||
-DLV_COLOR_DEPTH=32
|
||||
-DLV_MEM_SIZE=8388608
|
||||
-DLV_DPI_DEF=160
|
||||
-DLV_DRAW_COMPLEX=1
|
||||
-DLV_SHADOW_CACHE_SIZE=1
|
||||
-DLV_IMG_CACHE_DEF_SIZE=32
|
||||
-DLV_USE_LOG=1
|
||||
-DLV_LOG_LEVEL=LV_LOG_LEVEL_TRACE
|
||||
-DLV_LOG_PRINTF=1
|
||||
-DLV_USE_FONT_SUBPX=1
|
||||
-DLV_FONT_SUBPX_BGR=1
|
||||
-DLV_USE_PERF_MONITOR=1
|
||||
-DLV_USE_ASSERT_NULL=1
|
||||
-DLV_USE_ASSERT_MALLOC=1
|
||||
-DLV_USE_ASSERT_MEM_INTEGRITY=1
|
||||
-DLV_USE_ASSERT_OBJ=1
|
||||
-DLV_USE_ASSERT_STYLE=1
|
||||
-DLV_USE_USER_DATA=1
|
||||
-DLV_USE_LARGE_COORD=1
|
||||
-DLV_FONT_MONTSERRAT_8=1
|
||||
-DLV_FONT_MONTSERRAT_10=1
|
||||
-DLV_FONT_MONTSERRAT_12=1
|
||||
-DLV_FONT_MONTSERRAT_14=1
|
||||
-DLV_FONT_MONTSERRAT_16=1
|
||||
-DLV_FONT_MONTSERRAT_18=1
|
||||
-DLV_FONT_MONTSERRAT_20=1
|
||||
-DLV_FONT_MONTSERRAT_22=1
|
||||
-DLV_FONT_MONTSERRAT_24=1
|
||||
-DLV_FONT_MONTSERRAT_26=1
|
||||
-DLV_FONT_MONTSERRAT_28=1
|
||||
-DLV_FONT_MONTSERRAT_30=1
|
||||
-DLV_FONT_MONTSERRAT_32=1
|
||||
-DLV_FONT_MONTSERRAT_34=1
|
||||
-DLV_FONT_MONTSERRAT_36=1
|
||||
-DLV_FONT_MONTSERRAT_38=1
|
||||
-DLV_FONT_MONTSERRAT_40=1
|
||||
-DLV_FONT_MONTSERRAT_42=1
|
||||
-DLV_FONT_MONTSERRAT_44=1
|
||||
-DLV_FONT_MONTSERRAT_46=1
|
||||
-DLV_FONT_MONTSERRAT_48=1
|
||||
-DLV_FONT_MONTSERRAT_12_SUBPX=1
|
||||
-DLV_FONT_MONTSERRAT_28_COMPRESSED=1
|
||||
-DLV_FONT_DEJAVU_16_PERSIAN_HEBREW=1
|
||||
-DLV_FONT_SIMSUN_16_CJK=1
|
||||
-DLV_FONT_UNSCII_8=1
|
||||
-DLV_FONT_UNSCII_16=1
|
||||
-DLV_FONT_FMT_TXT_LARGE=1
|
||||
-DLV_USE_FONT_COMPRESSED=1
|
||||
-DLV_USE_BIDI=1
|
||||
-DLV_USE_ARABIC_PERSIAN_CHARS=1
|
||||
-DLV_USE_PERF_MONITOR=1
|
||||
-DLV_USE_MEM_MONITOR=1
|
||||
-DLV_LABEL_TEXT_SELECTION=1
|
||||
${LVGL_TEST_COMMON_EXAMPLE_OPTIONS}
|
||||
-DLV_FONT_DEFAULT=&lv_font_montserrat_24
|
||||
-DLV_USE_FS_STDIO=1
|
||||
-DLV_FS_STDIO_LETTER='A'
|
||||
-DLV_USE_FS_POSIX=1
|
||||
-DLV_FS_POSIX_LETTER='B'
|
||||
-DLV_USE_PNG=1
|
||||
-DLV_USE_BMP=1
|
||||
-DLV_USE_SJPG=1
|
||||
-DLV_USE_GIF=1
|
||||
-DLV_USE_QRCODE=1
|
||||
-DLV_USE_FRAGMENT=1
|
||||
-DLV_USE_IMGFONT=1
|
||||
-DLV_USE_MSG=1
|
||||
)
|
||||
|
||||
set(LVGL_TEST_OPTIONS_TEST_COMMON
|
||||
--coverage
|
||||
-DLV_COLOR_DEPTH=32
|
||||
-DLV_MEM_SIZE=2097152
|
||||
-DLV_SHADOW_CACHE_SIZE=10240
|
||||
-DLV_IMG_CACHE_DEF_SIZE=32
|
||||
-DLV_DITHER_GRADIENT=1
|
||||
-DLV_DITHER_ERROR_DIFFUSION=1
|
||||
-DLV_GRAD_CACHE_DEF_SIZE=8*1024
|
||||
-DLV_USE_LOG=1
|
||||
-DLV_LOG_PRINTF=1
|
||||
-DLV_USE_FONT_SUBPX=1
|
||||
-DLV_FONT_SUBPX_BGR=1
|
||||
-DLV_USE_ASSERT_NULL=0
|
||||
-DLV_USE_ASSERT_MALLOC=0
|
||||
-DLV_USE_ASSERT_MEM_INTEGRITY=0
|
||||
-DLV_USE_ASSERT_OBJ=0
|
||||
-DLV_USE_ASSERT_STYLE=0
|
||||
-DLV_USE_USER_DATA=1
|
||||
-DLV_USE_LARGE_COORD=1
|
||||
-DLV_FONT_MONTSERRAT_14=1
|
||||
-DLV_FONT_MONTSERRAT_16=1
|
||||
-DLV_FONT_MONTSERRAT_18=1
|
||||
-DLV_FONT_MONTSERRAT_24=1
|
||||
-DLV_FONT_MONTSERRAT_48=1
|
||||
-DLV_FONT_MONTSERRAT_12_SUBPX=1
|
||||
-DLV_FONT_MONTSERRAT_28_COMPRESSED=1
|
||||
-DLV_FONT_DEJAVU_16_PERSIAN_HEBREW=1
|
||||
-DLV_FONT_SIMSUN_16_CJK=1
|
||||
-DLV_FONT_UNSCII_8=1
|
||||
-DLV_FONT_UNSCII_16=1
|
||||
-DLV_FONT_FMT_TXT_LARGE=1
|
||||
-DLV_USE_FONT_COMPRESSED=1
|
||||
-DLV_USE_BIDI=1
|
||||
-DLV_USE_ARABIC_PERSIAN_CHARS=1
|
||||
-DLV_LABEL_TEXT_SELECTION=1
|
||||
-DLV_USE_FS_STDIO=1
|
||||
-DLV_FS_STDIO_LETTER='A'
|
||||
-DLV_FS_STDIO_CACHE_SIZE=100
|
||||
-DLV_USE_FS_POSIX=1
|
||||
-DLV_FS_POSIX_LETTER='B'
|
||||
-DLV_FS_POSIX_CACHE_SIZE=0
|
||||
${LVGL_TEST_COMMON_EXAMPLE_OPTIONS}
|
||||
-DLV_FONT_DEFAULT=&lv_font_montserrat_14
|
||||
-Wno-unused-but-set-variable # unused variables are common in the dual-heap arrangement
|
||||
-Wno-unused-variable
|
||||
-DLV_TEST_OPTION=5
|
||||
)
|
||||
|
||||
set(LVGL_TEST_OPTIONS_TEST_SYSHEAP
|
||||
${LVGL_TEST_OPTIONS_TEST_COMMON}
|
||||
-DLV_TEST_OPTION=5
|
||||
-DLVGL_CI_USING_SYS_HEAP
|
||||
-DLV_MEM_CUSTOM=1
|
||||
-fsanitize=address
|
||||
-Wno-unused-but-set-variable # unused variables are common in the dual-heap arrangement
|
||||
)
|
||||
|
||||
set(LVGL_TEST_OPTIONS_TEST_DEFHEAP
|
||||
${LVGL_TEST_OPTIONS_TEST_COMMON}
|
||||
-DLV_TEST_OPTION=5
|
||||
-DLVGL_CI_USING_DEF_HEAP
|
||||
-DLV_MEM_SIZE=2097152
|
||||
-fsanitize=address
|
||||
-fsanitize=leak
|
||||
-fsanitize=undefined
|
||||
--coverage
|
||||
)
|
||||
|
||||
if (OPTIONS_MINIMAL_MONOCHROME)
|
||||
set (BUILD_OPTIONS ${LVGL_TEST_OPTIONS_MINIMAL_MONOCHROME})
|
||||
if (OPTIONS_VG_LITE)
|
||||
set (BUILD_OPTIONS ${LVGL_TEST_OPTIONS_VG_LITE})
|
||||
elseif (OPTIONS_NORMAL_8BIT)
|
||||
set (BUILD_OPTIONS ${LVGL_TEST_OPTIONS_NORMAL_8BIT})
|
||||
elseif (OPTIONS_16BIT)
|
||||
set (BUILD_OPTIONS ${LVGL_TEST_OPTIONS_16BIT})
|
||||
elseif (OPTIONS_16BIT_SWAP)
|
||||
set (BUILD_OPTIONS ${LVGL_TEST_OPTIONS_16BIT_SWAP})
|
||||
elseif (OPTIONS_24BIT)
|
||||
set (BUILD_OPTIONS ${LVGL_TEST_OPTIONS_24BIT})
|
||||
elseif (OPTIONS_FULL_32BIT)
|
||||
set (BUILD_OPTIONS ${LVGL_TEST_OPTIONS_FULL_32BIT})
|
||||
elseif (OPTIONS_TEST_SYSHEAP)
|
||||
set (BUILD_OPTIONS ${LVGL_TEST_OPTIONS_TEST_SYSHEAP})
|
||||
set (TEST_LIBS --coverage -fsanitize=address)
|
||||
set (BUILD_OPTIONS ${LVGL_TEST_OPTIONS_TEST_SYSHEAP} -fsanitize=address -fsanitize=leak -fsanitize=undefined --coverage)
|
||||
filter_compiler_options (C TEST_LIBS --coverage -fsanitize=address -fsanitize=leak -fsanitize=undefined)
|
||||
set (LV_CONF_BUILD_DISABLE_EXAMPLES ON)
|
||||
set (ENABLE_TESTS ON)
|
||||
elseif (OPTIONS_TEST_DEFHEAP)
|
||||
set (BUILD_OPTIONS ${LVGL_TEST_OPTIONS_TEST_DEFHEAP})
|
||||
set (TEST_LIBS --coverage -fsanitize=address)
|
||||
filter_compiler_options (C TEST_LIBS --coverage -fsanitize=address -fsanitize=leak -fsanitize=undefined)
|
||||
set (LV_CONF_BUILD_DISABLE_EXAMPLES ON)
|
||||
set (ENABLE_TESTS ON)
|
||||
elseif (OPTIONS_TEST_MEMORYCHECK)
|
||||
# sanitizer is disabled because valgrind uses LD_PRELOAD and the
|
||||
# sanitizer lib needs to load first
|
||||
set (BUILD_OPTIONS ${LVGL_TEST_OPTIONS_TEST_SYSHEAP})
|
||||
set (LV_CONF_BUILD_DISABLE_EXAMPLES ON)
|
||||
set (ENABLE_TESTS ON)
|
||||
else()
|
||||
message(FATAL_ERROR "Must provide a known options value (check main.py?).")
|
||||
endif()
|
||||
|
||||
|
||||
if ($ENV{NON_AMD64_BUILD})
|
||||
set(BUILD_TARGET_DEF -DNON_AMD64_BUILD)
|
||||
message("Non AMD64 target is specified")
|
||||
endif()
|
||||
|
||||
# Options lvgl and examples are compiled with.
|
||||
set(COMPILE_OPTIONS
|
||||
-DLV_CONF_PATH=${LVGL_TEST_DIR}/src/lv_test_conf.h
|
||||
@@ -293,32 +143,51 @@ set(COMPILE_OPTIONS
|
||||
-Wmissing-prototypes
|
||||
-Wpointer-arith
|
||||
-Wmultichar
|
||||
-Wno-discarded-qualifiers
|
||||
-Wpedantic
|
||||
-Wreturn-type
|
||||
-Wshadow
|
||||
-Wshift-negative-value
|
||||
-Wsizeof-pointer-memaccess
|
||||
-Wstack-usage=5000
|
||||
#-Wstack-usage=6000
|
||||
-Wtype-limits
|
||||
-Wundef
|
||||
-Wuninitialized
|
||||
-Wunreachable-code
|
||||
-Werror=float-conversion
|
||||
-Werror=strict-aliasing
|
||||
-Wno-double-promotion
|
||||
-Wno-unused-but-set-parameter
|
||||
-Wno-unreachable-code
|
||||
${BUILD_OPTIONS}
|
||||
${BUILD_TARGET_DEF}
|
||||
)
|
||||
|
||||
filter_compiler_options(C LVGL_C_COMPILE_OPTIONS ${COMPILE_OPTIONS})
|
||||
|
||||
# Options test cases are compiled with.
|
||||
set(LVGL_TESTFILE_COMPILE_OPTIONS
|
||||
${COMPILE_OPTIONS}
|
||||
-Wno-missing-prototypes
|
||||
filter_compiler_options(C LVGL_TESTFILE_COMPILE_OPTIONS ${LVGL_C_COMPILE_OPTIONS} -Wno-missing-prototypes)
|
||||
|
||||
filter_compiler_options(CXX LVGL_CXX_COMPILE_OPTIONS
|
||||
${COMPILE_OPTIONS}
|
||||
-Wno-shadow
|
||||
-Wno-unused-parameter
|
||||
-Wno-c++11-extensions
|
||||
-Wno-missing-prototypes
|
||||
-Wno-deprecated-copy-with-user-provided-dtor
|
||||
-Wno-float-conversion
|
||||
-Wno-pedantic
|
||||
)
|
||||
|
||||
get_filename_component(LVGL_DIR ${LVGL_TEST_DIR} DIRECTORY)
|
||||
|
||||
# Include lvgl project file.
|
||||
include(${LVGL_DIR}/CMakeLists.txt)
|
||||
target_compile_options(lvgl PUBLIC ${COMPILE_OPTIONS})
|
||||
target_compile_options(lvgl_examples PUBLIC ${COMPILE_OPTIONS})
|
||||
target_compile_options(lvgl PUBLIC $<$<COMPILE_LANGUAGE:C>: ${LVGL_C_COMPILE_OPTIONS}>)
|
||||
target_compile_options(lvgl PUBLIC $<$<COMPILE_LANGUAGE:ASM>: ${LVGL_C_COMPILE_OPTIONS}>)
|
||||
target_compile_options(lvgl PUBLIC $<$<COMPILE_LANGUAGE:CXX>: ${LVGL_CXX_COMPILE_OPTIONS}>)
|
||||
if (TARGET lvgl_examples)
|
||||
target_compile_options(lvgl_examples PUBLIC ${LVGL_C_COMPILE_OPTIONS})
|
||||
endif()
|
||||
|
||||
|
||||
set(TEST_INCLUDE_DIRS
|
||||
@@ -327,43 +196,151 @@ set(TEST_INCLUDE_DIRS
|
||||
$<BUILD_INTERFACE:${LVGL_TEST_DIR}>
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE TEST_IMAGES_SRC ${LVGL_TEST_DIR}/test_images/*.c)
|
||||
|
||||
add_library(test_common
|
||||
STATIC
|
||||
src/lv_test_indev.c
|
||||
src/lv_test_init.c
|
||||
src/test_fonts/font_1.c
|
||||
src/test_fonts/font_2.c
|
||||
src/test_fonts/font_3.c
|
||||
src/lv_test_helpers.c
|
||||
src/test_assets/test_animimg001.c
|
||||
src/test_assets/test_animimg002.c
|
||||
src/test_assets/test_animimg003.c
|
||||
src/test_assets/test_img_cogwheel_i4.c
|
||||
src/test_assets/test_img_cogwheel_a8.c
|
||||
src/test_assets/test_img_cogwheel_rgb565.c
|
||||
src/test_assets/test_img_cogwheel_rgb565a8.c
|
||||
src/test_assets/test_img_cogwheel_xrgb8888.c
|
||||
src/test_assets/test_img_cogwheel_argb8888.c
|
||||
src/test_assets/test_font_1.c
|
||||
src/test_assets/test_font_2.c
|
||||
src/test_assets/test_font_3.c
|
||||
src/test_assets/test_font_montserrat_ascii_1bpp.c
|
||||
src/test_assets/test_font_montserrat_ascii_2bpp.c
|
||||
src/test_assets/test_font_montserrat_ascii_4bpp.c
|
||||
src/test_assets/test_font_montserrat_ascii_4bpp_compressed.c
|
||||
src/test_assets/test_font_1_bin.c
|
||||
src/test_assets/test_font_2_bin.c
|
||||
src/test_assets/test_font_3_bin.c
|
||||
src/test_assets/test_img_caret_down.c
|
||||
src/test_assets/test_arc_bg.c
|
||||
src/test_assets/test_img_lvgl_logo_png.c
|
||||
src/test_assets/test_img_lvgl_logo_jpg.c
|
||||
src/test_assets/test_img_emoji_F617.c
|
||||
src/test_assets/test_ubuntu_font.c
|
||||
src/test_assets/test_kern_one_otf.c
|
||||
unity/unity_support.c
|
||||
unity/unity.c
|
||||
${TEST_IMAGES_SRC}
|
||||
)
|
||||
target_include_directories(test_common PUBLIC ${TEST_INCLUDE_DIRS})
|
||||
target_compile_options(test_common PUBLIC ${LVGL_TESTFILE_COMPILE_OPTIONS})
|
||||
|
||||
# Some examples `#include "lvgl/lvgl.h"` - which is a path which is not
|
||||
# in this source repository. If this repo is in a directory names 'lvgl'
|
||||
# then we can add our parent directory to the include path.
|
||||
# TODO: This is not good practice and should be fixed.
|
||||
get_filename_component(LVGL_PARENT_DIR ${LVGL_DIR} DIRECTORY)
|
||||
target_include_directories(lvgl_examples PUBLIC $<BUILD_INTERFACE:${LVGL_PARENT_DIR}>)
|
||||
|
||||
# Generate one test executable for each source file pair.
|
||||
# The sources in src/test_runners is auto-generated, the
|
||||
# The sources in ${CMAKE_CURRENT_BINARY_DIR} is auto-generated, the
|
||||
# sources in src/test_cases is the actual test case.
|
||||
file( GLOB TEST_CASE_FILES src/test_cases/*.c )
|
||||
find_package(Ruby REQUIRED)
|
||||
set(generate_test_runner_rb
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/unity/generate_test_runner.rb)
|
||||
set(generate_test_runner_config ${CMAKE_CURRENT_SOURCE_DIR}/config.yml)
|
||||
|
||||
# libjpeg is required for the jpeg test case
|
||||
find_package(JPEG REQUIRED)
|
||||
include_directories(${JPEG_INCLUDE_DIR})
|
||||
|
||||
# libpng is required for the png test case
|
||||
find_package(PNG REQUIRED)
|
||||
include_directories(${PNG_INCLUDE_DIR})
|
||||
|
||||
# libfreetype is required for the font test case
|
||||
find_package(Freetype REQUIRED)
|
||||
include_directories(${FREETYPE_INCLUDE_DIRS})
|
||||
|
||||
# libinput is required for the libinput device driver test case
|
||||
find_package(Libinput OPTIONAL_COMPONENTS)
|
||||
include_directories(${LIBINPUT_INCLUDE_DIRS})
|
||||
|
||||
if (NOT LIBINPUT_FOUND)
|
||||
message("libinput not found, defaulting to 0")
|
||||
add_definitions(-DLV_USE_LIBINPUT=0)
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(xkbcommon pkg_check_modules xkbcommon)
|
||||
|
||||
if (NOT xkbcommon_FOUND)
|
||||
message("xkbcommon not found, defaulting to 0")
|
||||
add_definitions(-DLV_LIBINPUT_XKB=0)
|
||||
endif()
|
||||
|
||||
# libdrm is required for the DRM display driver test case
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/FindLibDRM.cmake)
|
||||
if(Libdrm_FOUND)
|
||||
include_directories(${Libdrm_INCLUDE_DIRS})
|
||||
else()
|
||||
message("libdrm not found, defaulting to 0")
|
||||
add_definitions(-DLV_USE_LINUX_DRM=0)
|
||||
endif()
|
||||
|
||||
# If we are running on mac, set LV_USE_LINUX_FBDEV to 0
|
||||
if(APPLE)
|
||||
add_definitions(-DLV_USE_LINUX_FBDEV=0)
|
||||
endif()
|
||||
|
||||
# disable test targets for build only tests
|
||||
if (ENABLE_TESTS)
|
||||
file(GLOB_RECURSE TEST_CASE_FILES src/test_cases/*.c)
|
||||
file(GLOB_RECURSE TEST_LIBS_FILES src/test_libs/*.c)
|
||||
else()
|
||||
set(TEST_CASE_FILES)
|
||||
set(TEST_LIBS_FILES)
|
||||
endif()
|
||||
|
||||
# build a test libs target
|
||||
if (TEST_LIBS_FILES)
|
||||
add_library(test_libs STATIC ${TEST_LIBS_FILES})
|
||||
target_include_directories(test_libs PUBLIC ${TEST_INCLUDE_DIRS} "src/test_libs")
|
||||
target_compile_options(test_libs PUBLIC ${LVGL_TESTFILE_COMPILE_OPTIONS})
|
||||
list(APPEND TEST_LIBS test_libs)
|
||||
endif()
|
||||
|
||||
foreach( test_case_fname ${TEST_CASE_FILES} )
|
||||
# If test file is foo/bar/baz.c then test_name is "baz".
|
||||
get_filename_component(test_name ${test_case_fname} NAME_WLE)
|
||||
if (${test_name} STREQUAL "_test_template")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
# gather all test cases
|
||||
list(APPEND TEST_CASES ${test_name})
|
||||
|
||||
# Create path to auto-generated source file.
|
||||
set(test_runner_fname src/test_runners/${test_name}_Runner.c)
|
||||
set(test_runner_fname ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_Runner.c)
|
||||
# Run ruby to generate source in build directory
|
||||
add_custom_command(
|
||||
OUTPUT ${test_runner_fname}
|
||||
COMMAND ${RUBY_EXECUTABLE} ${generate_test_runner_rb}
|
||||
${test_case_fname} ${test_runner_fname}
|
||||
${generate_test_runner_config}
|
||||
DEPENDS ${generate_test_runner_rb} ${test_case_fname}
|
||||
${generate_test_runner_config}
|
||||
)
|
||||
add_executable( ${test_name}
|
||||
${test_case_fname}
|
||||
${test_runner_fname}
|
||||
)
|
||||
target_link_libraries(${test_name} test_common lvgl_examples lvgl_demos lvgl png ${TEST_LIBS})
|
||||
target_link_libraries(${test_name} PRIVATE
|
||||
test_common
|
||||
lvgl_demos
|
||||
lvgl
|
||||
lvgl_thorvg
|
||||
${PNG_LIBRARIES}
|
||||
${FREETYPE_LIBRARIES}
|
||||
${LIBDRM_LIBRARIES}
|
||||
${LIBINPUT_LIBRARIES}
|
||||
${JPEG_LIBRARIES}
|
||||
m
|
||||
${TEST_LIBS})
|
||||
target_include_directories(${test_name} PUBLIC ${TEST_INCLUDE_DIRS})
|
||||
target_compile_options(${test_name} PUBLIC ${LVGL_TESTFILE_COMPILE_OPTIONS})
|
||||
|
||||
@@ -373,4 +350,11 @@ foreach( test_case_fname ${TEST_CASE_FILES} )
|
||||
COMMAND ${test_name})
|
||||
endforeach( test_case_fname ${TEST_CASE_FILES} )
|
||||
|
||||
add_custom_target(run
|
||||
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure --timeout 300
|
||||
WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
|
||||
DEPENDS ${TEST_CASES}
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PKG_Libdrm pkg_check_modules libdrm)
|
||||
|
||||
set(Libdrm_DEFINITIONS ${PKG_Libdrm_CFLAGS_OTHER})
|
||||
set(Libdrm_VERSION ${PKG_Libdrm_VERSION})
|
||||
|
||||
find_path(Libdrm_INCLUDE_DIR
|
||||
NAMES
|
||||
xf86drm.h
|
||||
HINTS
|
||||
${PKG_Libdrm_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(Libdrm_LIBRARY
|
||||
NAMES
|
||||
drm
|
||||
HINTS
|
||||
${PKG_Libdrm_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Libdrm
|
||||
FOUND_VAR
|
||||
Libdrm_FOUND
|
||||
REQUIRED_VARS
|
||||
Libdrm_LIBRARY
|
||||
Libdrm_INCLUDE_DIR
|
||||
VERSION_VAR
|
||||
Libdrm_VERSION
|
||||
)
|
||||
|
||||
if(Libdrm_FOUND AND NOT TARGET Libdrm::Libdrm)
|
||||
add_library(Libdrm::Libdrm UNKNOWN IMPORTED)
|
||||
set_target_properties(Libdrm::Libdrm PROPERTIES
|
||||
IMPORTED_LOCATION "${Libdrm_LIBRARY}"
|
||||
INTERFACE_COMPILE_OPTIONS "${Libdrm_DEFINITIONS}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Libdrm_INCLUDE_DIR}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Libdrm_INCLUDE_DIR}/libdrm"
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(Libdrm_LIBRARY Libdrm_INCLUDE_DIR)
|
||||
|
||||
set(Libdrm_LIBRARIES ${Libdrm_LIBRARY})
|
||||
set(Libdrm_INCLUDE_DIRS ${Libdrm_INCLUDE_DIR} "${Libdrm_INCLUDE_DIR}/libdrm")
|
||||
set(Libdrm_VERSION_STRING ${Libdrm_VERSION} ${PKG_Libdrm_LIBRARY_DIRS})
|
||||
@@ -18,6 +18,12 @@ scripts/install-prerequisites.sh
|
||||
3. Clean prior test build, build all build-only tests,
|
||||
run executable tests, and generate code coverage
|
||||
report `./tests/main.py --clean --report build test`.
|
||||
4. You can re-generate the test images by adding option `--update-image`.
|
||||
It relies on scripts/LVGLImage.py, which requires pngquant and pypng.
|
||||
You can run below command firstly and follow instructions in logs to install them.
|
||||
`./tests/main.py --update-image test`
|
||||
Note that different version of pngquant may generate different images.
|
||||
As of now the generated image on CI uses pngquant 2.13.1-1.
|
||||
|
||||
For full information on running tests run: `./tests/main.py --help`.
|
||||
|
||||
@@ -44,14 +50,7 @@ See the list of asserts [here](https://github.com/ThrowTheSwitch/Unity/blob/mast
|
||||
|
||||
There are some custom, LVGL specific asserts:
|
||||
- `TEST_ASSERT_EQUAL_SCREENSHOT("image1.png")` Render the active screen and compare its content with an image in the `ref_imgs` folder.
|
||||
If the compare fails `lvgl/test_screenshot_error.h` is created with the content of the frame buffer as an image.
|
||||
To see the that image `#include "test_screenshot_error.h"` and call `test_screenshot_error_show();`.
|
||||
- If the reference image is not found it will be created automatically from the rendered screen.
|
||||
- If the compare fails an `<image_name>_err.png` file will be created with the rendered content next to the reference image.
|
||||
- `TEST_ASSERT_EQUAL_COLOR(color1, color2)` Compare two colors.
|
||||
|
||||
### Adding new reference images
|
||||
The reference images can be taken by copy-pasting the test code in to LVGL simulator and saving the screen.
|
||||
LVGL needs to
|
||||
- 800x480 resolution
|
||||
- 32 bit color depth
|
||||
- `LV_USE_PERF_MONITOR` and `LV_USE_MEM_MONITOR` disabled
|
||||
- use the default theme, with the default color (don't set a theme manually)
|
||||
|
||||
@@ -2,21 +2,26 @@
|
||||
|
||||
import argparse
|
||||
import errno
|
||||
import glob
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
from itertools import chain
|
||||
from pathlib import Path
|
||||
|
||||
lvgl_test_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
lvgl_script_path = os.path.join(lvgl_test_dir, "../scripts")
|
||||
sys.path.append(lvgl_script_path)
|
||||
|
||||
from LVGLImage import LVGLImage, ColorFormat, CompressMethod
|
||||
|
||||
# Key values must match variable names in CMakeLists.txt.
|
||||
build_only_options = {
|
||||
'OPTIONS_MINIMAL_MONOCHROME': 'Minimal config monochrome',
|
||||
'OPTIONS_NORMAL_8BIT': 'Normal config, 8 bit color depth',
|
||||
# 'OPTIONS_NORMAL_8BIT': 'Normal config, 8 bit color depth',
|
||||
'OPTIONS_16BIT': 'Minimal config, 16 bit color depth',
|
||||
'OPTIONS_16BIT_SWAP': 'Normal config, 16 bit color depth swapped',
|
||||
'OPTIONS_24BIT': 'Normal config, 24 bit color depth',
|
||||
'OPTIONS_FULL_32BIT': 'Full config, 32 bit color depth',
|
||||
'OPTIONS_VG_LITE': 'VG-Lite simulator with full config, 32 bit color depth',
|
||||
}
|
||||
|
||||
test_options = {
|
||||
@@ -25,10 +30,6 @@ test_options = {
|
||||
}
|
||||
|
||||
|
||||
def is_valid_option_name(option_name):
|
||||
return option_name in build_only_options or option_name in test_options
|
||||
|
||||
|
||||
def get_option_description(option_name):
|
||||
if option_name in build_only_options:
|
||||
return build_only_options[option_name]
|
||||
@@ -43,22 +44,6 @@ def delete_dir_ignore_missing(dir_path):
|
||||
pass
|
||||
|
||||
|
||||
def generate_test_runners():
|
||||
'''Generate the test runner source code.'''
|
||||
global lvgl_test_dir
|
||||
os.chdir(lvgl_test_dir)
|
||||
delete_dir_ignore_missing('src/test_runners')
|
||||
os.mkdir('src/test_runners')
|
||||
|
||||
# TODO: Intermediate files should be in the build folders, not alongside
|
||||
# the other repo source.
|
||||
for f in glob.glob("./src/test_cases/test_*.c"):
|
||||
r = f[:-2] + "_Runner.c"
|
||||
r = r.replace("/test_cases/", "/test_runners/")
|
||||
subprocess.check_call(['ruby', 'unity/generate_test_runner.rb',
|
||||
f, r, 'config.yml'])
|
||||
|
||||
|
||||
def options_abbrev(options_name):
|
||||
'''Return an abbreviated version of the option name.'''
|
||||
prefix = 'OPTIONS_'
|
||||
@@ -66,7 +51,7 @@ def options_abbrev(options_name):
|
||||
return options_name[len(prefix):].lower()
|
||||
|
||||
|
||||
def get_base_buid_dir(options_name):
|
||||
def get_base_build_dir(options_name):
|
||||
'''Given the build options name, return the build directory name.
|
||||
|
||||
Does not return the full path to the directory - just the base name.'''
|
||||
@@ -78,7 +63,7 @@ def get_build_dir(options_name):
|
||||
|
||||
Returns absolute path to the build directory.'''
|
||||
global lvgl_test_dir
|
||||
return os.path.join(lvgl_test_dir, get_base_buid_dir(options_name))
|
||||
return os.path.join(lvgl_test_dir, get_base_build_dir(options_name))
|
||||
|
||||
|
||||
def build_tests(options_name, build_type, clean):
|
||||
@@ -105,13 +90,13 @@ def build_tests(options_name, build_type, clean):
|
||||
created_build_dir = True
|
||||
os.chdir(build_dir)
|
||||
if created_build_dir:
|
||||
subprocess.check_call(['cmake', '-DCMAKE_BUILD_TYPE=%s' % build_type,
|
||||
subprocess.check_call(['cmake', '-GNinja', '-DCMAKE_BUILD_TYPE=%s' % build_type,
|
||||
'-D%s=1' % options_name, '..'])
|
||||
subprocess.check_call(['cmake', '--build', build_dir,
|
||||
'--parallel', str(os.cpu_count())])
|
||||
|
||||
|
||||
def run_tests(options_name):
|
||||
def run_tests(options_name, test_suite):
|
||||
'''Run the tests for the given options name.'''
|
||||
|
||||
print()
|
||||
@@ -122,8 +107,15 @@ def run_tests(options_name):
|
||||
print('=' * len(label), flush=True)
|
||||
|
||||
os.chdir(get_build_dir(options_name))
|
||||
subprocess.check_call(
|
||||
['ctest', '--timeout', '30', '--parallel', str(os.cpu_count()), '--output-on-failure'])
|
||||
args = [
|
||||
'ctest',
|
||||
'--timeout', '300',
|
||||
'--parallel', str(os.cpu_count()),
|
||||
'--output-on-failure',
|
||||
]
|
||||
if test_suite is not None:
|
||||
args.extend(["--tests-regex", test_suite])
|
||||
subprocess.check_call(args)
|
||||
|
||||
|
||||
def generate_code_coverage_report():
|
||||
@@ -146,14 +138,37 @@ def generate_code_coverage_report():
|
||||
cmd = ['gcovr', '--root', root_dir, '--html-details', '--output',
|
||||
html_report_file, '--xml', 'report/coverage.xml',
|
||||
'-j', str(os.cpu_count()), '--print-summary',
|
||||
'--html-title', 'LVGL Test Coverage']
|
||||
for d in ('.*\\bexamples/.*', '\\bsrc/test_.*', '\\bsrc/lv_test.*', '\\bunity\\b'):
|
||||
cmd.extend(['--exclude', d])
|
||||
'--html-title', 'LVGL Test Coverage', '--filter', '../src/.*/lv_.*\.c']
|
||||
|
||||
subprocess.check_call(cmd)
|
||||
print("Done: See %s" % html_report_file, flush=True)
|
||||
|
||||
|
||||
def generate_test_images():
|
||||
invalids = (ColorFormat.UNKNOWN,)
|
||||
formats = [i for i in ColorFormat if i not in invalids]
|
||||
png_path = os.path.join(lvgl_test_dir, "test_images/pngs")
|
||||
pngs = list(Path(png_path).rglob("*.[pP][nN][gG]"))
|
||||
print(f"png files: {pngs}")
|
||||
|
||||
align_options = [1, 64]
|
||||
|
||||
for align in align_options:
|
||||
for compress in CompressMethod:
|
||||
compress_name = compress.name if compress != CompressMethod.NONE else "UNCOMPRESSED"
|
||||
outputs = os.path.join(lvgl_test_dir, f"test_images/stride_align{align}/{compress_name}/")
|
||||
os.makedirs(outputs, exist_ok=True)
|
||||
for fmt in formats:
|
||||
for png in pngs:
|
||||
img = LVGLImage().from_png(png, cf=fmt, background=0xffffff)
|
||||
img.adjust_stride(align=16)
|
||||
output = os.path.join(outputs, f"{Path(png).stem}_{fmt.name}.bin")
|
||||
img.to_bin(output, compress=compress)
|
||||
output = os.path.join(outputs, f"{Path(png).stem}_{fmt.name}_{compress.name}_align{align}.c")
|
||||
img.to_c_array(output, compress=compress)
|
||||
print(f"converting {os.path.basename(png)}, format: {fmt.name}, compress: {compress_name}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
epilog = '''This program builds and optionally runs the LVGL test programs.
|
||||
There are two types of LVGL tests: "build", and "test". The build-only
|
||||
@@ -164,6 +179,7 @@ if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Build and/or run LVGL tests.', epilog=epilog)
|
||||
parser.add_argument('--build-options', nargs=1,
|
||||
choices=list(chain(build_only_options, test_options)),
|
||||
help='''the build option name to build or run. When
|
||||
omitted all build configurations are used.
|
||||
''')
|
||||
@@ -173,9 +189,16 @@ if __name__ == "__main__":
|
||||
help='generate code coverage report for tests.')
|
||||
parser.add_argument('actions', nargs='*', choices=['build', 'test'],
|
||||
help='build: compile build tests, test: compile/run executable tests.')
|
||||
parser.add_argument('--test-suite', default=None,
|
||||
help='select test suite to run')
|
||||
parser.add_argument('--update-image', action='store_true', default=False,
|
||||
help='Update test image using LVGLImage.py script')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.update_image:
|
||||
generate_test_images()
|
||||
|
||||
if args.build_options:
|
||||
options_to_build = args.build_options
|
||||
else:
|
||||
@@ -187,20 +210,13 @@ if __name__ == "__main__":
|
||||
else:
|
||||
options_to_build = test_options
|
||||
|
||||
for opt in options_to_build:
|
||||
if not is_valid_option_name(opt):
|
||||
print('Invalid build option "%s"' % opt, file=sys.stderr)
|
||||
sys.exit(errno.EINVAL)
|
||||
|
||||
generate_test_runners()
|
||||
|
||||
for options_name in options_to_build:
|
||||
is_test = options_name in test_options
|
||||
build_type = 'Debug'
|
||||
build_tests(options_name, build_type, args.clean)
|
||||
if is_test:
|
||||
try:
|
||||
run_tests(options_name)
|
||||
run_tests(options_name, args.test_suite)
|
||||
except subprocess.CalledProcessError as e:
|
||||
sys.exit(e.returncode)
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
test_file
|
||||
@@ -1,8 +1,9 @@
|
||||
LVGL_DIR := $(CURDIR)/../..
|
||||
LVGL_PATH := $(CURDIR)/../..
|
||||
$(info LVGL_PATH is set to: $(LVGL_PATH))
|
||||
include ../../lvgl.mk
|
||||
|
||||
CSRCS += test.c
|
||||
CFLAGS += -DLV_CONF_SKIP=1 -DLV_BUILD_TEST=1 -I$(LVGL_DIR)/..
|
||||
CFLAGS += -Werror -DLV_CONF_SKIP=1 -DLV_BUILD_TEST=1 -DLV_USE_DEV_VERSION -I$(LVGL_PATH)/..
|
||||
COBJS := $(patsubst %.c, %.o, $(CSRCS))
|
||||
|
||||
test_file: $(COBJS)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#if LV_BUILD_TEST
|
||||
#include <stdio.h>
|
||||
#include "lvgl/lvgl.h"
|
||||
#include "../../lvgl.h"
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
lv_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,370 @@
|
||||
"""
|
||||
The test script will only run the one test on microptyhon. It is not a
|
||||
framework that can be used for other tests. This has a reduced code footprint.
|
||||
entrypoint API is almost the same as the framework.
|
||||
|
||||
|
||||
Requirements
|
||||
Python >= 3.10
|
||||
|
||||
pillow library
|
||||
|
||||
add the following to the CI prior to the test running
|
||||
|
||||
python3 -m pip install pillow
|
||||
|
||||
Example command line to run the test. I suggest doing this from the root of the
|
||||
binding directory. It is just a simple location to do it from.
|
||||
|
||||
Paths that are passed in MUST be relitive to the current working directory.
|
||||
python3 lib/lv_bindings/lvgl/tests/micropy_test/__init__.py --artifact-path=lib/lv_bindings/lvgl/tests/micropy_test/artifacts --mpy-path=ports/unix/build-standard/micropython
|
||||
|
||||
"""
|
||||
import os
|
||||
import time
|
||||
import signal
|
||||
import argparse
|
||||
import binascii
|
||||
import unittest
|
||||
import threading
|
||||
import subprocess
|
||||
|
||||
from PIL import Image as Image
|
||||
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
debug_log = None
|
||||
|
||||
|
||||
def log(*args):
|
||||
args = ' '.join(repr(arg) for arg in args)
|
||||
debug_log.write(args + '\n')
|
||||
|
||||
if DEBUG:
|
||||
sys.stdout.write('\033[31;1m' + args + '\033[0m\n')
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
BASE_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__)))
|
||||
TEST_PATH = os.path.join(BASE_PATH, 'micropy.py')
|
||||
IMG_PATH = os.path.join(BASE_PATH, '../ref_imgs/binding.png')
|
||||
|
||||
CTRL_C = b'\x03' # 2 times to exit any running code
|
||||
CTRL_D = b'\x04' # exit paste mode committing and running what has been pasted
|
||||
CTRL_E = b'\x05' # enter paste mode
|
||||
|
||||
PASTE_PROMPT = b'==='
|
||||
REPL_PROMPT = b'>>>'
|
||||
|
||||
os.environ['MICROPYINSPECT'] = '1'
|
||||
|
||||
|
||||
class TestData:
|
||||
|
||||
def __init__(self):
|
||||
self.watchdog_timer = time.time()
|
||||
self.result = None
|
||||
self.error_data = ''
|
||||
self.event = threading.Event()
|
||||
|
||||
|
||||
class MicroPython_Test(unittest.TestCase):
|
||||
# these are here simply to make an IDE happy. Their values get dynamically
|
||||
# set when the class gets constructed
|
||||
process: subprocess.Popen = None
|
||||
exit_event: threading.Event = None
|
||||
|
||||
@classmethod
|
||||
def send(cls, cmd):
|
||||
if cls.process is None:
|
||||
return
|
||||
|
||||
log('<---', cmd)
|
||||
cls.process.stdin.write(cmd)
|
||||
cls.process.stdin.flush()
|
||||
|
||||
@classmethod
|
||||
def read_until(cls, marker):
|
||||
micropy_data = b''
|
||||
error_data = b''
|
||||
|
||||
log('MARKER', marker)
|
||||
|
||||
logged = False
|
||||
|
||||
while (
|
||||
not micropy_data.endswith(marker) and
|
||||
not cls.exit_event.is_set()
|
||||
):
|
||||
try:
|
||||
char = cls.process.stdout.read(1)
|
||||
except: # NOQA
|
||||
break
|
||||
|
||||
if char:
|
||||
micropy_data += char
|
||||
logged = False
|
||||
else:
|
||||
logged = True
|
||||
log('--->', micropy_data)
|
||||
|
||||
if micropy_data.endswith(b'\nERROR END\n'):
|
||||
error_data = micropy_data.split(b'\nERROR START\n')[-1].split(b'\nERROR END\n')[0]
|
||||
micropy_data = b''
|
||||
log('---> ERROR: ', error_data)
|
||||
logged = True
|
||||
break
|
||||
|
||||
if not logged:
|
||||
log('--->', micropy_data)
|
||||
|
||||
if cls.exit_event.is_set():
|
||||
log('--EXIT EVENT SET')
|
||||
|
||||
if micropy_data:
|
||||
return micropy_data.replace(marker, b''), error_data
|
||||
|
||||
return micropy_data, error_data
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
os.chdir(os.path.dirname(__file__))
|
||||
cls.exit_event = threading.Event()
|
||||
|
||||
log(f'--SETTING UP')
|
||||
cls.process = subprocess.Popen(
|
||||
['bash'],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
stdin=subprocess.PIPE,
|
||||
env=os.environ,
|
||||
shell=True,
|
||||
preexec_fn=os.setsid
|
||||
)
|
||||
log(f'--RUNNING MICROPYTHON ({MICROPYTHON_PATH})')
|
||||
|
||||
cls.send(b'cd ' + os.path.dirname(__file__).encode('utf-8') + b'\n')
|
||||
cls.send(MICROPYTHON_PATH.encode('utf-8') + b'\n')
|
||||
_, error_data = cls.read_until(b'>>>')
|
||||
|
||||
if error_data:
|
||||
raise RuntimeError(error_data)
|
||||
|
||||
log('--MICROPYTHON STARTED')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
log('--TEARDOWN STARTED')
|
||||
|
||||
if cls.process is not None:
|
||||
cls.send(CTRL_C)
|
||||
cls.send(CTRL_C)
|
||||
cls.send(CTRL_D)
|
||||
|
||||
if not cls.process.stdin.closed:
|
||||
cls.process.stdin.close()
|
||||
|
||||
os.killpg(os.getpgid(cls.process.pid), signal.SIGTERM)
|
||||
|
||||
cls.process.wait()
|
||||
|
||||
if not cls.process.stdout.closed:
|
||||
cls.process.stdout.close()
|
||||
|
||||
if not cls.process.stderr.closed:
|
||||
cls.process.stderr.close()
|
||||
|
||||
cls.process = None
|
||||
|
||||
log(f'--TEARDOWN FINISHED')
|
||||
|
||||
def test_1_image_compare(self):
|
||||
image = Image.open(IMG_PATH)
|
||||
res_img = image.convert('RGB')
|
||||
image.close()
|
||||
res_data = list(res_img.getdata())
|
||||
res_img.close()
|
||||
|
||||
with open(TEST_PATH, 'rb') as f:
|
||||
test_code = f.read()
|
||||
|
||||
log(f'--RUNNING TEST ({TEST_PATH})')
|
||||
|
||||
test_code = test_code.strip()
|
||||
|
||||
if self.__class__.process is None:
|
||||
self.fail('MicroPython failure.')
|
||||
|
||||
self.send(CTRL_E)
|
||||
|
||||
_, error_data = self.read_until(PASTE_PROMPT)
|
||||
if error_data:
|
||||
self.fail(error_data)
|
||||
|
||||
test_code = test_code.split(b'\r\n')
|
||||
|
||||
for i, line in enumerate(test_code):
|
||||
self.send(line + b'\n')
|
||||
_, error_data = self.read_until(b'\n')
|
||||
|
||||
if error_data:
|
||||
self.fail(error_data)
|
||||
|
||||
time.sleep(0.002)
|
||||
|
||||
# self.read_until(b'# end\n')
|
||||
|
||||
def _do(td: TestData):
|
||||
self.send(CTRL_D)
|
||||
td.error_data = b''
|
||||
td.watchdog_timer = time.time()
|
||||
|
||||
td.result = []
|
||||
|
||||
try:
|
||||
_, td.error_data = self.read_until(b'FRAME START\n')
|
||||
td.watchdog_timer = time.time()
|
||||
|
||||
lne, td.error_data = self.read_until(b'\n')
|
||||
|
||||
while (
|
||||
b'FRAME END' not in lne and
|
||||
not td.error_data and
|
||||
not self.__class__.exit_event.is_set()
|
||||
):
|
||||
td.watchdog_timer = time.time()
|
||||
td.result.append(lne)
|
||||
lne, td.error_data = self.read_until(b'\n')
|
||||
|
||||
if td.error_data:
|
||||
return
|
||||
|
||||
if self.__class__.exit_event.is_set():
|
||||
return
|
||||
|
||||
except: # NOQA
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
|
||||
td.error_data = traceback.format_exc()
|
||||
return
|
||||
|
||||
td.event.set()
|
||||
|
||||
test_data = TestData()
|
||||
|
||||
t = threading.Thread(
|
||||
target=_do,
|
||||
args=(test_data,)
|
||||
)
|
||||
t.daemon = True
|
||||
test_data.watchdog_timer = time.time()
|
||||
|
||||
t.start()
|
||||
|
||||
while (
|
||||
(time.time() - test_data.watchdog_timer) * 1000 <= 20000 and
|
||||
not test_data.event.is_set()
|
||||
):
|
||||
test_data.event.wait(0.05)
|
||||
|
||||
if not test_data.event.is_set():
|
||||
self.__class__.exit_event.set()
|
||||
# self.read_until(REPL_PROMPT)
|
||||
|
||||
self.send(CTRL_C)
|
||||
self.send(CTRL_C)
|
||||
|
||||
width = 800
|
||||
height = 480
|
||||
|
||||
if test_data.error_data:
|
||||
self.fail(test_data.error_data)
|
||||
|
||||
try:
|
||||
frame = bytearray(
|
||||
b''.join(binascii.unhexlify(lne) for lne in test_data.result)
|
||||
)
|
||||
|
||||
# I don't exactly know why the byte order is backwards but it is
|
||||
frame = bytes(bytearray([
|
||||
item for j in range(0, len(frame), 3)
|
||||
for item in [frame[j + 2], frame[j + 1], frame[j]]
|
||||
]))
|
||||
|
||||
image = Image.new('RGB', (width, height))
|
||||
image.frombytes(frame)
|
||||
img = image.convert('RGB')
|
||||
image.close()
|
||||
|
||||
byte_data = list(img.getdata())
|
||||
img.save(os.path.join(ARTIFACT_PATH, f'frame.png'), 'PNG')
|
||||
img.close()
|
||||
|
||||
with open(os.path.join(ARTIFACT_PATH, f'frame.bin'), 'wb') as f:
|
||||
# have to flatten the data and remove the alpha
|
||||
# from the PIL image it is formatted as
|
||||
# [(r, g, b), (r, g, b)]
|
||||
f.write(bytes(bytearray([
|
||||
item for sublist in byte_data
|
||||
for item in sublist
|
||||
])))
|
||||
|
||||
except: # NOQA
|
||||
import traceback
|
||||
|
||||
self.fail(traceback.format_exc())
|
||||
|
||||
self.assertEqual(res_data, byte_data, 'Frames do not match')
|
||||
|
||||
|
||||
cwd = os.path.abspath(os.getcwd())
|
||||
|
||||
ARTIFACT_PATH = os.path.join(cwd, 'artifacts')
|
||||
MICROPYTHON_PATH = os.path.join(cwd, 'micropython')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
arg_parser = argparse.ArgumentParser()
|
||||
arg_parser.add_argument(
|
||||
'--artifact-path',
|
||||
dest='artifact_path',
|
||||
help='path to save artifacts to',
|
||||
action='store'
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
'--mpy-path',
|
||||
dest='mpy_path',
|
||||
help='path to micropython',
|
||||
action='store'
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
'--debug',
|
||||
dest='debug',
|
||||
help='debug output',
|
||||
action='store_true'
|
||||
)
|
||||
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
ARTIFACT_PATH = os.path.join(cwd, args.artifact_path)
|
||||
MICROPYTHON_PATH = os.path.join(cwd, args.mpy_path)
|
||||
DEBUG = args.debug
|
||||
|
||||
if not os.path.exists(ARTIFACT_PATH):
|
||||
raise RuntimeError(f'Artifact path does not exist ({ARTIFACT_PATH})')
|
||||
|
||||
if not os.path.exists(MICROPYTHON_PATH):
|
||||
raise RuntimeError(f'MicroPython binary not found ({MICROPYTHON_PATH})')
|
||||
|
||||
debug_log_path = os.path.join(ARTIFACT_PATH, 'debug.log')
|
||||
debug_log = open(debug_log_path, 'w')
|
||||
|
||||
unittest.main(argv=[sys.argv[0], '-v'])
|
||||
|
||||
debug_log.close()
|
||||
print(f'View the debug output in "{debug_log_path}"')
|
||||
|
After Width: | Height: | Size: 38 KiB |
@@ -0,0 +1,448 @@
|
||||
import io
|
||||
|
||||
import lvgl as lv
|
||||
import ubinascii
|
||||
import fs_driver
|
||||
import sys
|
||||
|
||||
|
||||
if not lv.is_initialized():
|
||||
lv.init()
|
||||
|
||||
try:
|
||||
lv.log_register_print_cb # NOQA
|
||||
|
||||
raise RuntimeError('Logging in LVGL MUST be disabled to run the tests.')
|
||||
except AttributeError:
|
||||
pass
|
||||
except RuntimeError as exc:
|
||||
buf = io.StringIO()
|
||||
sys.print_exception(exc, buf)
|
||||
|
||||
print('ERROR START')
|
||||
print(buf.getvalue())
|
||||
print('ERROR END')
|
||||
raise
|
||||
|
||||
fs_drv = lv.fs_drv_t()
|
||||
fs_driver.fs_register(fs_drv, 'A')
|
||||
|
||||
WIDTH = 800
|
||||
HEIGHT = 480
|
||||
|
||||
|
||||
def test_func_wrapper(func):
|
||||
def _wrapper(*args, **kwargs):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except Exception as exc:
|
||||
buf = io.StringIO()
|
||||
sys.print_exception(exc, buf)
|
||||
|
||||
print('ERROR START')
|
||||
print(buf.getvalue())
|
||||
print('ERROR END')
|
||||
|
||||
return _wrapper
|
||||
|
||||
|
||||
CAPTURE_FRAME = False
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def flush(disp, area, color_p):
|
||||
|
||||
x1 = area.x1
|
||||
x2 = area.x2
|
||||
y1 = area.y1
|
||||
y2 = area.y2
|
||||
|
||||
size = (x2 - x1 + 1) * (y2 - y1 + 1) * lv.color_format_get_size(
|
||||
disp.get_color_format()
|
||||
)
|
||||
data_view = color_p.__dereference__(size)
|
||||
byte_count = 0
|
||||
|
||||
print('FRAME START')
|
||||
sys.stdout.flush()
|
||||
|
||||
while byte_count != size:
|
||||
chunk_size = min(size - byte_count, 512)
|
||||
chunk = data_view[byte_count:chunk_size + byte_count]
|
||||
byte_count += chunk_size
|
||||
print(ubinascii.hexlify(bytes(chunk)).decode('utf-8'))
|
||||
sys.stdout.flush()
|
||||
|
||||
print('FRAME END')
|
||||
sys.stdout.flush()
|
||||
|
||||
disp.flush_ready()
|
||||
|
||||
|
||||
disp_drv = lv.display_create(WIDTH, HEIGHT)
|
||||
disp_drv.set_flush_cb(flush)
|
||||
disp_drv.set_color_format(lv.COLOR_FORMAT.RGB888)
|
||||
|
||||
buf = lv.draw_buf_create(WIDTH, HEIGHT, lv.COLOR_FORMAT.RGB888, 0)
|
||||
color_size = lv.color_format_get_size(disp_drv.get_color_format())
|
||||
disp_drv.set_draw_buffers(buf, None)
|
||||
disp_drv.set_render_mode(lv.DISPLAY_RENDER_MODE.FULL)
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def GRID_FR(x):
|
||||
return lv.COORD.MAX - 100 + x
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def CANVAS_BUF_SIZE(w, h, bpp, stride):
|
||||
return ((((w * bpp + 7) >> 3) + stride - 1) & ~(
|
||||
stride - 1)) * h + lv.DRAW_BUF_ALIGN
|
||||
|
||||
|
||||
event_flag = False
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def event_callback(e):
|
||||
global event_flag
|
||||
event_flag = True
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def test_event():
|
||||
scr = lv.screen_active()
|
||||
|
||||
scr.add_event_cb(event_callback, lv.EVENT.CLICKED, None)
|
||||
|
||||
scr.send_event(lv.EVENT.CLICKED, None)
|
||||
|
||||
if not event_flag:
|
||||
raise RuntimeError('Event failure')
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def create_ui():
|
||||
# Create a colors
|
||||
c1 = lv.color_hex(0xff0000)
|
||||
c2 = lv.palette_darken(lv.PALETTE.BLUE, 2)
|
||||
c3 = c1.mix(c2, lv.OPA._60)
|
||||
|
||||
# Create a style
|
||||
style_big_font = lv.style_t()
|
||||
style_big_font.init()
|
||||
|
||||
# Try to load as built in font and if not load it using tiny TTF
|
||||
try:
|
||||
font_montserrat_24 = lv.font_montserrat_24
|
||||
except AttributeError:
|
||||
font_montserrat_24 = lv.tiny_ttf_create_file('A:font_montserrat_24.ttf', 32)
|
||||
|
||||
style_big_font.set_text_font(font_montserrat_24)
|
||||
|
||||
# Get the active screen
|
||||
scr = lv.screen_active()
|
||||
|
||||
# Declare static array of integers, and test grid setting options
|
||||
gird_cols = [300, GRID_FR(3), GRID_FR(2), lv.GRID_TEMPLATE_LAST]
|
||||
gird_rows = [100, GRID_FR(1), lv.GRID_CONTENT, lv.GRID_TEMPLATE_LAST]
|
||||
scr.set_grid_dsc_array(gird_cols, gird_rows)
|
||||
|
||||
chart_type_subject = lv.subject_t()
|
||||
chart_type_subject.init_int(0)
|
||||
|
||||
# Create a widget
|
||||
dropdown = lv.dropdown(scr)
|
||||
|
||||
# Pass a string as argument
|
||||
dropdown.set_options("Lines\nBars")
|
||||
|
||||
# Use grid align options
|
||||
dropdown.set_grid_cell(
|
||||
lv.GRID_ALIGN.CENTER,
|
||||
0,
|
||||
1,
|
||||
lv.GRID_ALIGN.CENTER,
|
||||
0,
|
||||
1
|
||||
)
|
||||
|
||||
# Bind to a subject
|
||||
dropdown.bind_value(chart_type_subject)
|
||||
|
||||
# Create a chart with an external array of points
|
||||
chart = lv.chart(lv.screen_active())
|
||||
chart.set_grid_cell(lv.GRID_ALIGN.STRETCH, 0, 1, lv.GRID_ALIGN.CENTER, 1, 1)
|
||||
|
||||
series = chart.add_series(c3, lv.chart.AXIS.PRIMARY_X)
|
||||
|
||||
chart_y_array = [10, 25, 50, 40, 30, 35, 60, 65, 70, 75]
|
||||
|
||||
chart.set_ext_y_array(series, chart_y_array)
|
||||
|
||||
# Add custom observer callback
|
||||
chart_type_subject.add_observer_obj(
|
||||
lambda _, __: chart_type_observer_cb(chart, chart_type_subject),
|
||||
chart,
|
||||
None
|
||||
)
|
||||
|
||||
# Manually set the subject's value
|
||||
chart_type_subject.set_int(1)
|
||||
|
||||
label = lv.label(scr)
|
||||
label.set_grid_cell(lv.GRID_ALIGN.START, 1, 1, lv.GRID_ALIGN.CENTER, 0, 1)
|
||||
|
||||
# Apply styles on main part and default state
|
||||
label.set_style_bg_opa(lv.OPA._70, 0)
|
||||
label.set_style_bg_color(c1, 0)
|
||||
label.set_style_text_color(c2, 0)
|
||||
label.add_style(style_big_font, 0)
|
||||
|
||||
# Declare an array of strings
|
||||
btnmatrix_options = ["First", "Second", "\n", "Third", ""]
|
||||
|
||||
btnmatrix_ctrl = [lv.buttonmatrix.CTRL.DISABLED,
|
||||
2 | lv.buttonmatrix.CTRL.CHECKED, 1]
|
||||
|
||||
btnmatrix = lv.buttonmatrix(scr)
|
||||
btnmatrix.set_grid_cell(
|
||||
lv.GRID_ALIGN.STRETCH,
|
||||
1,
|
||||
1,
|
||||
lv.GRID_ALIGN.STRETCH,
|
||||
1,
|
||||
1
|
||||
)
|
||||
# Pass string and enum arrays
|
||||
btnmatrix.set_map(btnmatrix_options)
|
||||
btnmatrix.set_ctrl_map(btnmatrix_ctrl)
|
||||
# Add style to non main part and non default state
|
||||
btnmatrix.add_style(style_big_font, lv.PART.ITEMS | lv.STATE.CHECKED)
|
||||
|
||||
btnmatrix.set_selected_button(1)
|
||||
btnmatrix.add_event_cb(
|
||||
lambda _: buttonmatrix_event_cb(btnmatrix, label),
|
||||
lv.EVENT.VALUE_CHANGED,
|
||||
None
|
||||
)
|
||||
btnmatrix.send_event(lv.EVENT.VALUE_CHANGED, None)
|
||||
|
||||
# Create a base object
|
||||
cont = lv.obj(scr)
|
||||
# Span 2 rows
|
||||
cont.set_grid_cell(lv.GRID_ALIGN.STRETCH, 2, 1, lv.GRID_ALIGN.STRETCH, 0, 2)
|
||||
|
||||
# Apply flex layout
|
||||
cont.set_flex_flow(lv.FLEX_FLOW.COLUMN)
|
||||
|
||||
btn1 = list_button_create(cont)
|
||||
btn2 = list_button_create(cont)
|
||||
btn3 = list_button_create(cont)
|
||||
btn4 = list_button_create(cont)
|
||||
btn5 = list_button_create(cont)
|
||||
btn6 = list_button_create(cont)
|
||||
btn7 = list_button_create(cont)
|
||||
btn8 = list_button_create(cont)
|
||||
btn9 = list_button_create(cont)
|
||||
btn10 = list_button_create(cont)
|
||||
|
||||
a = lv.anim_t()
|
||||
a.init()
|
||||
a.set_var(btn1)
|
||||
a.set_values(lv.OPA.COVER, lv.OPA._50)
|
||||
a.set_custom_exec_cb(lambda _, v: opa_anim_cb(btn1, v)) # Pass a callback
|
||||
a.set_time(300)
|
||||
a.set_path_cb(lv.anim_t.path_ease_out)
|
||||
a.start()
|
||||
|
||||
btn2.add_flag(lv.obj.FLAG.HIDDEN)
|
||||
|
||||
btn_label = btn3.get_child(0)
|
||||
btn_label.set_text("A multi-line text with a ° symbol")
|
||||
btn_label.set_width(lv.pct(100))
|
||||
|
||||
a = lv.anim_t()
|
||||
a.init()
|
||||
a.set_var(btn4)
|
||||
a.set_values(lv.OPA.COVER, lv.OPA._50)
|
||||
a.set_custom_exec_cb(lambda _, v: opa_anim_cb(btn4, v)) # Pass a callback
|
||||
a.set_path_cb(lv.anim_t.path_ease_out)
|
||||
a.set_time(300)
|
||||
a.set_repeat_count(lv.ANIM_REPEAT_INFINITE)
|
||||
a.start()
|
||||
|
||||
# Wait and delete the button with the animation
|
||||
|
||||
cont.get_child(3).delete()
|
||||
# Large byte array
|
||||
|
||||
canvas_buf = bytearray(CANVAS_BUF_SIZE(400, 100, 16, 1))
|
||||
|
||||
canvas = lv.canvas(scr)
|
||||
canvas.set_grid_cell(lv.GRID_ALIGN.START, 0, 2, lv.GRID_ALIGN.START, 2, 1)
|
||||
# Test RGB565 rendering
|
||||
canvas.set_buffer(
|
||||
lv.draw_buf_align(canvas_buf, lv.COLOR_FORMAT.RGB565),
|
||||
400,
|
||||
100,
|
||||
lv.COLOR_FORMAT.RGB565
|
||||
)
|
||||
canvas.fill_bg(c2, lv.OPA.COVER)
|
||||
draw_to_canvas(canvas)
|
||||
|
||||
test_img_lvgl_logo_jpg_data = (
|
||||
b'\xFF\xD8\xFF\xE0\x00\x10\x4A\x46\x49\x46\x00\x01\x01\x01\x01\x2C\x01\x2C\x00\x00\xFF\xFE\x00\x13\x43\x72\x65\x61\x74\x65\x64\x20\x77\x69\x74\x68\x20\x47\x49\x4D\x50\xFF\xDB\x00\x43\x00\x08\x06\x06\x07\x06\x05\x08\x07\x07\x07\x09\x09\x08\x0A\x0C\x15\x0E\x0C\x0B\x0B\x0C\x19\x12\x13\x0F\x15\x1E\x1B\x20\x1F\x1E\x1B\x1D\x1D\x21\x25\x30\x29\x21\x23\x2D\x24\x1D\x1D\x2A\x39\x2A\x2D\x31\x33\x36\x36\x36\x20\x28\x3B\x3F\x3A\x34\x3E\x30\x35\x36\x33\xFF\xDB\x00\x43\x01\x09\x09\x09\x0C\x0B\x0C\x18\x0E\x0E\x18\x33\x22\x1D\x22\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33'
|
||||
b'\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\xFF\xC0\x00\x11\x08\x00\x21\x00\x69\x03\x01\x11\x00\x02\x11\x01\x03\x11\x01\xFF\xC4\x00\x1F\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\xFF\xC4\x00\xB5\x10\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01\x7D\x01\x02\x03\x00\x04\x11\x05\x12\x21\x31\x41\x06\x13\x51\x61\x07\x22\x71\x14\x32\x81\x91\xA1\x08\x23\x42\xB1\xC1\x15\x52\xD1\xF0\x24\x33\x62\x72\x82\x09\x0A\x16\x17\x18\x19\x1A\x25\x26\x27\x28\x29\x2A\x34\x35\x36\x37\x38\x39\x3A\x43\x44\x45\x46\x47\x48\x49\x4A\x53\x54\x55'
|
||||
b'\x56\x57\x58\x59\x5A\x63\x64\x65\x66\x67\x68\x69\x6A\x73\x74\x75\x76\x77\x78\x79\x7A\x83\x84\x85\x86\x87\x88\x89\x8A\x92\x93\x94\x95\x96\x97\x98\x99\x9A\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFF\xC4\x00\x1F\x01\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\xFF\xC4\x00\xB5\x11\x00\x02\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04\x00\x01\x02\x77\x00\x01\x02\x03\x11\x04\x05\x21\x31\x06\x12\x41'
|
||||
b'\x51\x07\x61\x71\x13\x22\x32\x81\x08\x14\x42\x91\xA1\xB1\xC1\x09\x23\x33\x52\xF0\x15\x62\x72\xD1\x0A\x16\x24\x34\xE1\x25\xF1\x17\x18\x19\x1A\x26\x27\x28\x29\x2A\x35\x36\x37\x38\x39\x3A\x43\x44\x45\x46\x47\x48\x49\x4A\x53\x54\x55\x56\x57\x58\x59\x5A\x63\x64\x65\x66\x67\x68\x69\x6A\x73\x74\x75\x76\x77\x78\x79\x7A\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x92\x93\x94\x95\x96\x97\x98\x99\x9A\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFF\xDA\x00\x0C\x03\x01\x00\x02\x11\x03'
|
||||
b'\x11\x00\x3F\x00\x4F\x11\xFC\x6B\xF1\x25\x8F\x89\x35\x2B\x2B\x2B\x7B\x04\xB7\xB6\xB9\x78\x50\x49\x13\x33\x10\xAC\x57\x24\xEE\x1D\x71\x9A\x00\xCB\xFF\x00\x85\xEB\xE2\xEF\xF9\xE7\xA6\xFF\x00\xDF\x86\xFF\x00\xE2\xA9\x88\xD7\xF0\xE7\xC5\x5F\x1B\xF8\x9B\x57\x5D\x36\xD6\x4D\x0E\x09\x59\x19\xC3\xDC\xC6\xC8\xB8\x03\x3D\x77\x1E\x69\x0C\xF5\x4F\x87\xFE\x25\xBB\xF1\x4F\x84\xE3\xD4\x6F\xA3\x85\x2E\x44\xAF\x14\x9E\x47\xDC\x62\xA7\x19\x1C\x9A\x00\xD7\xD0\xB5\xBB\x5F\x11\x69\x11\x6A\x56\x42\x41\x04\x8C\xCA\xA2\x45\xC3\x65\x58\xA9\xE3\xEA\x0D\x00\x26\xB9\xAE\xDA\x78\x7A\xCE\x2B\xBB\xE1\x20\xB7\x79\xD2\x16\x91\x14\x11\x19\x63\x80\xCD\xCF\x0B\x9C\x73'
|
||||
b'\xEF\x40\x1A\x74\x01\x43\x5A\xD6\x2D\x34\x0D\x22\xE3\x53\xBE\x66\x10\x42\x01\x21\x46\x59\x89\x38\x00\x0E\xE4\x92\x00\x14\x00\xEB\xCD\x56\xCF\x4D\xD3\x0E\xA3\xA8\xCE\xB6\x76\xEA\xA1\x9D\xA7\x21\x76\xE7\xB1\xF7\xF6\x14\x01\xCE\xAF\xC4\x0B\x69\xD7\xCD\xB4\xD0\x7C\x43\x75\x6D\xD4\x5C\x45\xA7\xB6\xC2\x3D\x40\x24\x12\x3E\x82\x80\x36\xB4\x4F\x11\xE9\x7E\x21\x8A\x47\xD3\xEE\x0B\x3C\x27\x6C\xD0\xC8\x86\x39\x62\x3E\x8C\x8D\x82\x28\x01\xE9\xAD\xDA\xC9\xE2\x29\xB4\x35\x12\x7D\xAE\x2B\x65\xB9\x63\xB7\xE5\xD8\x58\xA8\xE7\xD7\x20\xD0\x06\x95\x00\x14\x01\xF3\x87\x88\x6F\x3C\x26\x3C\x49\xAA\x09\xFC\x20\x25\x98\x5D\xCA\x1E\x4F\xED\x29\x57\x7B\x6F\x39'
|
||||
b'\x38\x1C\x0C\x9E\x71\x5C\x13\xC6\xB8\xC9\xAB\x6C\x7D\x66\x1F\x86\x63\x56\x94\x6A\x7B\x4B\x5D\x27\xB7\x75\xEA\x72\x3E\x3C\xD2\xAC\xB4\x5F\x18\xDE\xD8\xE9\xD1\x34\x56\x88\x23\x68\xE3\x67\x2D\xB7\x74\x6A\xC4\x64\xF2\x79\x26\xBB\xD3\xBA\x3E\x52\x4B\x96\x4D\x1C\xE5\x32\x4F\xA6\x7E\x09\x7F\xC9\x37\x8F\xFE\xBE\x65\xFE\x62\x90\xCD\x4F\x85\x5F\xF2\x4F\x6C\x7F\xEB\xB4\xFF\x00\xFA\x39\xE8\x03\xA4\xD6\xB4\xAB\x7D\x73\x44\xBC\xD2\xEE\x86\x61\xBA\x89\xA3\x6F\x6C\xF4\x23\xDC\x1C\x1F\xC2\x80\x31\xBC\x05\xAA\xDC\x6A\x1E\x1C\x16\x97\xE7\xFE\x26\x7A\x64\x8D\x65\x76\x0F\x52\xE9\xC0\x6F\xF8\x12\xE0\xFE\x34\x01\x4F\x5C\xFF\x00\x8A\x8B\xC7\x3A\x66\x82\xBF'
|
||||
b'\x35\x9E\x98\x06\xA1\x7D\xE8\x5F\xA4\x28\x7F\x1C\xB6\x3D\x85\x00\x45\x35\xB4\x7E\x27\xF8\x9F\x3D\xB5\xE8\x12\xD8\xE8\x16\xF1\x49\x1D\xBB\x0C\xAB\x5C\x49\x92\x1C\x8E\xFB\x54\x71\xE8\x4D\x00\x77\x34\x01\x02\x2D\xAA\xDE\x4A\xD1\xAC\x22\xE5\x95\x7C\xD2\xB8\xDE\x40\xE9\x9E\xF8\xE4\xE2\x80\x39\x3B\x5F\xF9\x2C\x7A\x87\xFD\x81\x61\xFF\x00\xD1\xAD\x40\x1D\x9D\x00\x14\x01\xF3\xC6\xBD\xFF\x00\x08\x5F\xFC\x24\x5A\x9F\xDA\x06\xBF\xE7\xFD\xAE\x5F\x33\xCB\x30\xED\xDD\xBC\xE7\x19\xE7\x19\xAF\x26\xA7\xB1\xE7\x77\xBF\xE0\x7E\x87\x83\xFE\xD2\xFA\xBD\x3E\x4E\x4B\x59\x5A\xFC\xD7\xB5\x89\xBC\x79\x61\xE0\xC9\xBC\x5D\x73\x26\xA0\x75\xE1\x72\x63\x8B\x7F\xD9'
|
||||
b'\xCC\x3B\x31\xE5\xAE\x31\xBB\x9E\x98\xCF\xBD\x76\x4F\x15\x0A\x6F\x95\xA3\xE6\xB0\xD9\x0E\x23\x17\x4F\xDB\x46\x49\x27\x7E\xFD\xFD\x0E\x1B\xC6\x7A\x06\x9D\xA1\x5D\x69\xAD\xA5\xCD\x75\x25\xA5\xF5\x92\xDC\xA8\xBA\xDB\xBD\x72\xCC\x30\x76\xF1\xFC\x35\xD3\x09\x29\xC5\x49\x1E\x3E\x26\x84\xB0\xF5\x65\x4A\x5B\xA7\x63\xDC\xFE\x09\x7F\xC9\x37\x8F\xFE\xBE\x65\xFE\x62\x99\x89\xA1\xF0\xB2\x68\x93\xE1\xFD\x92\xB4\xA8\x0F\x9D\x3F\x05\x87\xFC\xF6\x7A\x00\xED\x16\x68\x9D\xB6\xAC\x88\xC7\xD0\x30\x34\x01\xC2\x6B\x97\x90\x78\x27\xC7\x2B\xAE\x5C\x37\x95\xA4\xEB\x10\x18\x6E\xDB\xB2\x4F\x1A\x96\x46\xFA\xB2\x82\xBF\x80\xA0\x0D\x3F\x00\xD9\x4E\x34\x79\xB5\xBB'
|
||||
b'\xF4\x2B\xA8\x6B\x33\x1B\xB9\x41\xEA\x88\x78\x8D\x3F\xE0\x29\x8F\xCC\xD0\x05\x1D\x66\x56\xF0\x87\x8D\x9B\xC4\x73\x46\xCD\xA3\x6A\x50\x25\xBD\xF4\xA8\xA5\x8D\xBC\x88\x4E\xC9\x1B\x1F\xC2\x41\x20\x9E\xD4\x01\xD8\x5B\x6A\x36\x37\x96\xCB\x73\x6D\x79\x04\xD0\x30\xC8\x92\x39\x03\x29\x1F\x51\x40\x1C\x96\x83\x79\x6D\xA8\x7C\x4D\xF1\x0D\xC5\x9C\xF1\xDC\x40\x96\x56\xD1\x34\x91\x36\xE5\x0E\x0B\xE5\x72\x38\xC8\xC8\xE2\x80\x16\x09\x12\x3F\x8C\x5A\x81\x77\x55\x1F\xD8\xB0\xF5\x38\xFF\x00\x96\xAD\x40\x1D\x8F\xDA\x20\xFF\x00\x9E\xD1\xFF\x00\xDF\x42\x80\x1D\xBD\x3F\xBE\xBF\x9D\x00\x79\x46\xA9\xF0\x6A\x6D\x47\x56\xBC\xBD\x1A\xDA\x20\xB8\x9D\xE5\x08\x6D'
|
||||
b'\x89\xDB\xB9\x89\xC6\x77\x7B\xD7\x04\xF0\x5C\xD2\x6F\x98\xFA\xCC\x3F\x13\x46\x95\x28\xD3\xF6\x57\xB2\x4B\x7E\xCB\xD0\xB7\xE2\x3F\x84\xD2\xEB\xDA\xDC\xBA\x82\xEB\x09\x08\x91\x11\x76\x1B\x72\xD8\xDA\x81\x7A\xEE\xF6\xAA\xAB\x84\xE7\x97\x35\xCC\x70\x3C\x42\xB0\xB4\x15\x2F\x67\x7B\x5F\xAF\x77\x7E\xC5\x4F\x12\x7C\x1A\x97\x5E\x8F\x49\x55\xD6\xD2\x13\x61\x64\xB6\xA4\x9B\x62\xDB\xF0\xCC\x77\x7D\xEE\x3E\xF7\x4A\xEA\xA7\x1E\x48\xA8\xF6\x3C\x1C\x5D\x7F\xAC\x57\x9D\x5B\x5B\x99\xDC\xEE\x3C\x15\xE1\x64\xF0\x7F\x86\x61\xD2\x16\xE4\xDC\x95\x66\x77\x94\xAE\xDD\xC5\x8F\x61\x93\x81\x56\x73\x91\x37\xC3\xCF\x08\x33\x16\x6F\x0F\x58\x12\x4E\x49\x31\x75\xA0'
|
||||
b'\x0B\x7A\x6F\x83\xFC\x3B\xA3\xDE\xAD\xE6\x9D\xA3\xDA\x5A\xDC\xA8\x20\x49\x12\x60\x80\x7A\xD0\x05\xFD\x4F\x4A\xB0\xD6\x6C\xCD\xA6\xA5\x69\x15\xD5\xB9\x60\xC6\x39\x57\x23\x23\xA1\xA0\x0B\x6A\xA1\x54\x2A\x80\x00\x18\x00\x76\xA0\x01\x95\x5D\x4A\xB2\x86\x52\x30\x41\x19\x06\x80\x39\xB9\xBE\x1E\xF8\x42\x79\xCC\xD2\x78\x7A\xC3\x79\x39\x38\x88\x00\x4F\xD0\x71\x40\x1B\xB6\x56\x16\x9A\x6D\xAA\xDB\x58\xDA\xC3\x6D\x02\x7D\xD8\xE1\x40\x8A\x3F\x01\x40\x19\xDA\xA7\x84\xBC\x3F\xAD\xDD\x8B\xBD\x4F\x49\xB5\xBB\xB8\x0A\x10\x49\x2A\x64\xED\x1D\x07\xEA\x68\x02\x8F\xFC\x2B\xBF\x07\xFF\x00\xD0\xBB\x61\xFF\x00\x7E\xA8\x03\x73\xFB\x32\xCB\xFE\x7D\xD2\x80\x2D'
|
||||
b'\xD0\x01\x40\x05\x00\x14\x00\x50\x01\x40\x05\x00\x14\x00\x50\x01\x40\x05\x00\x14\x00\x50\x01\x40\x1F\xFF\xD9'
|
||||
)
|
||||
|
||||
test_img_lvgl_logo_jpg = lv.image_dsc_t(
|
||||
dict(
|
||||
header=dict(cf=lv.COLOR_FORMAT.RAW_ALPHA, w=105, h=33),
|
||||
data_size=1947,
|
||||
data=test_img_lvgl_logo_jpg_data
|
||||
)
|
||||
)
|
||||
|
||||
img = lv.image(scr)
|
||||
img.set_src(test_img_lvgl_logo_jpg)
|
||||
img.align(lv.ALIGN.BOTTOM_RIGHT, -20, -20)
|
||||
img.add_flag(lv.obj.FLAG.IGNORE_LAYOUT)
|
||||
|
||||
img = lv.image(scr)
|
||||
img.set_src("A:test_img_lvgl_logo.png")
|
||||
img.set_pos(500, 420)
|
||||
img.add_flag(lv.obj.FLAG.IGNORE_LAYOUT)
|
||||
img.set_rotation(200)
|
||||
img.set_scale_x(400)
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def chart_type_observer_cb(chart, subject):
|
||||
v = subject.get_int()
|
||||
# chart = observer.get_target()
|
||||
chart.set_type(lv.chart.TYPE.LINE if v == 0 else lv.chart.TYPE.BAR)
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def buttonmatrix_event_cb(buttonmatrix, label):
|
||||
# label = e.get_user_data()
|
||||
# buttonmatrix = e.get_target()
|
||||
idx = buttonmatrix.get_selected_button()
|
||||
text = buttonmatrix.get_button_text(idx)
|
||||
label.set_text(text)
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def list_button_create(parent):
|
||||
btn = lv.button(parent)
|
||||
btn.set_size(lv.pct(100), lv.SIZE_CONTENT)
|
||||
|
||||
# Get an integer
|
||||
idx = btn.get_index()
|
||||
|
||||
# Formatted string for label
|
||||
label = lv.label(btn)
|
||||
label.set_text(lv.SYMBOL.FILE + " Item %d" % idx)
|
||||
|
||||
return btn
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def opa_anim_cb(button, value):
|
||||
try:
|
||||
button.set_style_opa(value, 0)
|
||||
except: # NOQA
|
||||
pass
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def draw_to_canvas(canvas):
|
||||
layer = lv.layer_t()
|
||||
canvas.init_layer(layer)
|
||||
|
||||
# Use draw descriptors
|
||||
|
||||
test_img_lvgl_logo_png_data = (
|
||||
b'\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x69\x00\x00\x00\x21\x08\x06\x00\x00\x00\xDA\x89\x85\x3B\x00\x00\x00\x06\x62\x4B\x47\x44\x00\x00\x00\x00\x00\x00\xF9\x43\xBB\x7F\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x2E\x23\x00\x00\x2E\x23\x01\x78\xA5\x3F\x76\x00\x00\x00\x07\x74\x49\x4D\x45\x07\xE7\x09\x12\x12\x25\x07\x59\xA0\x4E\xA5\x00\x00\x00\x19\x74\x45\x58\x74\x43\x6F\x6D\x6D\x65\x6E\x74\x00\x43\x72\x65\x61\x74\x65\x64\x20\x77\x69\x74\x68\x20\x47\x49\x4D\x50\x57\x81\x0E\x17\x00\x00\x06\xB9\x49\x44\x41\x54\x68\xDE\xED\x9A\x7F\x8C\x5D\x45\x15\xC7\x3F\xE7\xBE\xF7\x76\xA9\x20\x18\x03\x9A\x6A\x77\xE6\xDD'
|
||||
b'\xB7\x6B\x8A\x49\xC3\x1A\xB5\x25\x80\xB5\xE2\x6A\x2B\x0D\x46\x71\x89\x8A\xBF\x48\x4C\xD5\xD4\x46\x08\x58\x48\x10\xC5\xE8\x3F\xA6\x68\x6B\xE4\x0F\x85\x22\x68\x53\x6D\x9A\x40\x31\x40\xC0\x92\xB6\xD0\x62\x53\x4A\xAC\x44\xA2\xAD\xA4\x76\xF7\xDE\xB9\xAF\x3F\x0C\x0A\xD2\x96\x6D\xD9\xDD\xB7\xF7\xF8\xC7\x9B\xCA\x76\xF7\xFD\x5C\x77\xDD\xD7\xE4\x7D\x93\x97\x97\xB9\x33\x77\x66\xCE\xF9\xCE\x39\x73\xE6\xCC\x85\x36\xDA\x68\xE3\x7F\x87\x00\x98\x7C\xBE\x13\x95\xE5\x40\x0F\x5A\x7E\x36\x8D\x23\x0C\xA1\x6C\x4D\x92\x68\xA0\xAD\xEE\x29\xAA\xD0\x5A\x13\x28\x99\xCD\xC0\xF5\x67\x48\x9B\x01\x9C\x00\x96\x26\x2E\x7A\xBE\xAD\xF2\xE6\x91\x85\xCC\x42\xA0\x7F\x06'
|
||||
b'\x08\x2A\x01\x81\xFF\x5D\x08\xDC\x02\x7C\x7E\x7C\x83\xAE\xAE\x82\x48\xA0\x9D\x80\x04\xA2\xC3\x71\x1C\xA7\xF5\x3A\x35\xB6\x90\x45\x35\x07\x68\x92\x44\x6F\x4C\x75\x72\xF3\xC2\x30\x08\x52\x3A\x01\x4D\x5C\xFD\x7E\xAC\x0D\x73\xAA\xBC\x05\xD1\x9C\x57\xD5\x88\xA2\xA7\x8B\x2E\x1E\x6D\x64\x3C\x6B\x0B\x19\x55\xED\x40\x34\x4D\x5C\x3C\xDC\xCC\x5C\x03\x85\x8B\xBD\x22\xA7\x13\x03\xC0\xE5\xC0\xA7\x80\xD3\xFE\xD9\x3B\x27\x99\xB1\xF0\x56\xE0\x79\xE0\x40\xAA\xD2\xDB\x58\xD7\xDA\x8B\xB0\x1F\xE1\xAF\xC6\x86\xF3\xA7\xEC\x42\x52\xBE\x08\xBC\x04\x3C\x62\xF2\x85\x6C\x45\x22\x4D\x3E\x6B\x6C\xF8\x31\x63\xC3\x5F\x2B\xBC\x88\x30\x08\x52\x04\x8A\xC0\xA0\x20\x7F'
|
||||
b'\x36\x36\x7C\xC0\xD8\x70\x89\xC9\x87\x99\x9A\xB3\x46\xAF\x43\x78\x09\xE4\x31\x63\xC3\x6C\x53\x24\xCD\x90\x85\x3E\x9B\xB8\xE8\x05\xA1\xF4\x24\x70\xAC\xCE\xF8\xEF\x06\x8C\x22\xB9\x86\x28\x4A\xF5\x45\xE0\x35\xA0\x1B\x58\x31\x95\xC9\x19\x53\xC8\x08\x7C\x0B\x30\xC0\x13\x49\x3C\x58\x9A\x68\xE1\xC6\x86\x57\x07\x22\x7B\x80\x6D\xC0\x8D\xC0\x7C\x20\x07\xFC\xC3\xCB\x94\xF5\xCF\xBE\x0A\xEC\x44\x79\xDA\xD8\xB0\xD6\x42\x9B\xE3\xC7\x9B\xAB\xA2\xB4\x02\x49\xFD\xC6\x86\xB7\x2B\xD9\xB5\x80\x9D\xCE\x8E\x8B\xC5\xB8\x04\xFC\xD8\x17\x57\xD8\x7C\x78\x49\xB3\x7D\xA8\x68\x1F\xB0\x10\x38\x26\xE8\x86\xB3\x09\xCC\x8B\x04\x7A\x07\xF0\xD4\x99\x36\xC0\xF7\x80\x45'
|
||||
b'\x88\xBE\x23\x71\x51\x98\xB8\xA8\xA0\xA2\x97\x80\xF6\x02\xB7\x01\x09\xF0\x61\xE0\x59\x63\xC3\x65\x33\xB0\x27\xCD\x08\x2E\x04\xD6\xCC\xD8\x4E\xAA\x3C\x86\x10\x03\x79\x55\xBE\x0C\xAC\x6B\xF4\x55\x6B\xC3\x40\xE1\x26\x5F\x7C\xD0\xB9\xF8\xF5\x71\xFB\x94\x90\xF2\x5D\xE0\x87\x80\x02\xBF\x50\xE1\x8E\x62\x1C\x1D\x9F\xB4\x58\xE2\x78\x14\xD8\x0F\xEC\x37\xA6\x70\x1F\xA2\x6B\x80\x65\x40\x34\xDD\xE2\x06\xC0\xCB\x40\xCA\x39\x84\x24\x89\x86\x80\xFB\x7D\x71\xA5\xB5\xB6\xA3\x71\x7E\xB9\xD4\x2B\xF3\x34\x70\xEF\x59\xCA\x48\xE9\x03\xEE\xF2\xC5\xEF\xA8\xE8\xAA\x4A\x04\x4D\x9E\xCF\xE0\x49\x90\x55\x22\xB2\x30\x71\xD1\xC1\x69\xB7\xA4\x4C\x90\xEE\x2B\x8D\x05'
|
||||
b'\xBD\x12\xC8\xDC\x2A\x62\x65\x51\xBE\x06\x5C\xD7\x4A\x44\xA9\x72\x9F\x08\xAB\x81\x1E\x25\xB8\x1E\xD8\xD4\xE0\xAB\xAB\xBD\x07\xD9\x90\xB8\xE8\xF0\x9B\x51\xA3\xED\x04\xD6\xFA\xBA\x8D\x28\x6B\x8A\x2E\x6E\x78\xF3\x48\xDC\xA0\x02\xAF\xCE\x48\x08\xBE\x35\x72\x73\xB4\x1C\x89\x9D\x57\x79\xE1\xF1\xF8\x52\x1B\xFE\xC0\x47\x6A\x41\xAB\x90\x54\x4C\xA2\x57\x8C\x0D\x37\x03\x2B\x81\x6F\x74\xF7\xBC\x67\xF3\xC0\xA1\xBF\xA7\xB5\xC3\xF7\xF0\x5D\xFE\xB8\x51\x9A\x68\x45\x10\x7C\x04\xB8\x0C\x18\x42\xB9\x33\x49\x22\x6D\x15\x59\xB3\x0A\x4B\x80\x5F\xD6\x68\x93\x57\xD8\x20\x65\xC2\x5A\x0D\x3F\xF5\x11\xDE\xE2\xD1\x91\xD2\x95\xC0\xEE\x3A\xED\xBF\xEE\xF7\xCB\xA7'
|
||||
b'\x12\x17\xED\x9B\x50\xF7\x05\xFF\xFF\x50\x92\x44\xC5\x56\x12\x32\x68\xC0\x3A\x02\x5A\x15\x2A\x87\x80\x47\x01\x41\xB8\x79\x5E\x97\x91\x1A\x01\xC3\x45\x9E\xA4\x14\xF8\xD9\xF8\xBA\x8B\xBB\x17\x08\xB0\xC8\x17\x9F\x6E\x35\x31\x5B\x97\x80\x86\x02\x88\x41\x05\x7E\xEE\xDD\xF2\xB5\x22\xD9\x7C\x8D\x80\xA1\x1F\x98\x0B\xFC\x2D\x95\x74\xFB\xF8\xBA\xF3\x4B\xA7\x2E\xA0\x7C\xA8\x4F\x81\x43\x6D\x92\xA6\x19\x63\xA3\x23\x3B\x81\xE7\x80\xF3\x44\xF4\x96\x4A\x6D\xBA\x0A\x61\xCE\x07\x0C\x00\x6B\x0F\xC7\xEE\xAC\x54\x4E\x0A\x19\xAF\x0B\x05\x86\xA7\x32\x0F\x63\xC3\x15\xC6\x86\x1B\x8D\x0D\xFB\xDB\x24\x4D\xC0\x91\xA3\x47\xC6\x5B\xD3\x0D\xC6\x16\xDE\x3E\x29\x05'
|
||||
b'\x34\xC6\x32\x9F\x1D\x38\x2A\x2A\x5B\x26\xD6\x67\x44\x87\x81\x51\xAF\x8F\x8B\xA6\x38\x95\xCB\x81\x2F\xF9\xE0\xA3\x4D\xD2\x24\x12\x08\xB6\x00\xAE\xEC\xB2\xF4\xC6\x0A\x4D\x6E\xF2\xB2\xAE\x77\xC9\xE0\x89\x89\x95\x71\x1C\x9D\xF6\xEF\x0B\xB0\xA0\x15\xDD\x5D\xBD\x2C\xEE\x28\xC2\x49\x60\xA4\x55\x49\x72\x6E\xE0\x8D\x71\xC1\xC0\x2A\x6B\xED\x9C\x71\x6E\x68\x11\xF0\x51\xE0\x84\x0A\xEB\x6B\x74\xF3\x8C\xFF\xFF\x4C\xAB\xC9\x97\x55\x78\x46\xE0\x9A\x2A\xE7\xA4\x14\xF8\x83\xA0\xAF\x81\x5C\xA1\x10\x56\x5E\xC9\x04\x94\xEF\xA3\x6E\x98\xC5\x48\x6F\x13\xA2\xDF\x07\x0A\x4A\x70\x0D\xF0\xC8\x99\x8C\x04\xE5\x3D\x67\x4B\x31\x8E\x8E\xD5\x48\x45\xFC\x06\xE1\x56'
|
||||
b'\x60\xB1\xB1\xE1\x92\xC4\x45\xBB\x5A\x86\xA4\x71\x7E\x78\x4E\x25\x92\x14\x3A\xB6\xC7\x71\x90\x96\x09\x7A\x5B\x95\x03\xEF\xAE\x3E\xD3\xBD\x2B\x23\x69\x3F\xD0\x31\x1B\x82\x24\xC9\xE0\xCB\xC6\x86\x0F\x00\xDF\x06\x6E\xEB\xE9\x9E\xFF\xBB\xE1\xD2\x48\x17\xE5\x3B\xAC\x12\xF0\x93\x9A\x2E\x25\xE0\x40\xAA\x3C\x01\x7C\x1A\xB8\xA7\xCB\x14\x16\x17\x2B\xB8\xC6\x59\x21\x49\xE0\x6A\x60\x73\x75\x7F\xCF\xDD\x29\xFC\x0A\x78\xD8\xAF\xC8\x4A\xD8\x74\xA4\x23\xB3\xD2\x8C\xA6\xB3\x9B\x03\x54\xD6\x23\x7C\x13\x58\x38\x52\x1A\xB9\x4A\xE0\x5A\xEF\x21\x9E\x94\xF2\xDD\x51\x55\xC4\x71\x94\x5A\x1B\xDE\xAC\x70\x25\x70\x99\x88\x3E\x64\x6C\xFE\xB3\x89\x8B\x8F\xCF\x36'
|
||||
b'\x49\x41\x0D\xC5\xBF\x19\xFC\xD4\x6F\x93\x6D\x85\x15\x97\x24\xD1\x41\x60\xAB\x97\xE9\x76\xE0\x2B\xBE\xEA\x1E\xE7\xA2\xBA\x0B\xC8\xB9\x28\x01\x3E\x07\x9C\x04\x96\x82\x3C\x67\x6C\xD8\x67\x4C\x4F\xA6\x7A\xE8\x5D\x08\x8C\x0D\xDF\x0F\x7C\x68\x26\xDD\x5D\x4B\x04\x68\x82\x5E\x65\x6C\xBE\xD1\xBB\xA1\xE3\x89\x8B\x77\x57\xB1\xFC\x35\x5A\xCE\x33\x7E\xD2\x3F\xDA\x97\xCB\xE5\xB6\x37\x4C\xB4\x8B\x76\x1A\x1B\x2E\x05\x7E\x0B\xBC\x17\xD8\x86\x8C\xED\x35\x36\xFC\x3D\xC8\x1F\x11\x2D\xA2\xAA\xA8\xCC\x45\x78\x1F\xE8\xC7\x81\x3E\xAF\xCB\x18\x78\xBC\xCE\x10\x17\x88\xB2\xDC\xD8\xFC\x58\x63\xCE\x41\x0E\xB4\x0C\x49\xC0\xBA\x26\x3E\xB3\x78\x01\xF8\x40\x15\xA9'
|
||||
b'\xFE\x84\xB0\x97\xB2\xDB\x02\xB8\x77\xE0\xD0\xC1\xB1\xA6\x2C\xD2\x45\x7B\x4D\x3E\xFC\x20\xCA\x6A\x9F\x4A\xBA\xA2\xFC\x53\x9F\xC1\x94\x89\x53\xFD\x27\x70\xBF\x90\xAE\x73\xCE\xBD\x52\xA7\xFB\x10\xE4\xD1\x26\x14\x73\x6B\x76\x76\xCD\x27\x1D\x51\x64\x23\x70\x7E\x93\xAF\x56\x4D\x80\xBA\x24\x2A\x19\x1B\xDE\xE5\xDD\x56\x49\x48\x37\x4D\xC9\x75\xC6\xD1\xBF\x81\x3B\x8D\xC9\xFF\x08\x91\x4F\x78\xA2\x7A\x7C\x90\x75\xE6\x5A\x62\x00\xD8\x13\x08\xDB\xE2\x38\x1A\xAA\x63\x12\x03\xC8\x7F\xEF\xC0\x9A\x59\xBD\x7F\xF9\x7F\x92\x94\x4C\xDE\x03\xE2\x53\x94\xBF\x22\x9A\xDE\x81\x5C\xB4\x03\xD8\x31\x3D\xFB\x5C\xFC\xBA\x0F\x9A\x1E\x9E\x37\x2F\x94\x20\x53\x3E\x99'
|
||||
b'\x24\xCE\x69\x73\xFD\x44\x7B\x80\x3D\x53\xDD\x93\x4A\xF5\xD2\x63\x0A\xF5\xDC\x45\x89\x52\xA9\x04\x0C\x55\x39\x6F\x1D\x05\xEE\x3E\xD7\x33\x1B\x87\x0F\xCF\xCE\x1D\x93\x1C\x84\xCE\xB4\xBC\xC9\x76\x56\x39\x03\xED\x50\xF8\x97\xC0\x72\xCA\x77\x31\x95\xB0\xFB\x52\x70\xC6\xE4\x7B\x09\x64\xC1\x84\x1E\x4E\x29\xEC\x2A\xBA\xE8\x55\xDA\x68\xA3\x8D\x36\xDA\x68\xA3\x8D\x73\x1A\xFF\x01\xC1\xBA\x4F\x53\x6B\xDA\x6F\x58\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82'
|
||||
)
|
||||
|
||||
test_img_lvgl_logo_png = lv.image_dsc_t(
|
||||
dict(
|
||||
header=dict(cf=lv.COLOR_FORMAT.RAW_ALPHA, w=105, h=33),
|
||||
data_size=1873,
|
||||
data=test_img_lvgl_logo_png_data
|
||||
)
|
||||
)
|
||||
|
||||
image_draw_dsc = lv.draw_image_dsc_t()
|
||||
|
||||
image_draw_dsc.init()
|
||||
image_draw_dsc.src = test_img_lvgl_logo_png
|
||||
|
||||
coords = lv.area_t(
|
||||
dict(
|
||||
x1=10,
|
||||
y1=10,
|
||||
x2=10 + test_img_lvgl_logo_png.header.w - 1,
|
||||
y2=10 + test_img_lvgl_logo_png.header.h - 1
|
||||
)
|
||||
)
|
||||
lv.draw_image(layer, image_draw_dsc, coords)
|
||||
|
||||
# Reuse the draw descriptor
|
||||
coords.move(40, 40)
|
||||
image_draw_dsc.opa = lv.OPA._50
|
||||
lv.draw_image(layer, image_draw_dsc, coords)
|
||||
|
||||
line_draw_dsc = lv.draw_line_dsc_t()
|
||||
line_draw_dsc.init()
|
||||
line_draw_dsc.color = lv.color_hex3(0xCA8)
|
||||
line_draw_dsc.width = 8
|
||||
line_draw_dsc.round_end = 1
|
||||
line_draw_dsc.round_start = 1
|
||||
line_draw_dsc.p1.x = 150
|
||||
line_draw_dsc.p1.y = 30
|
||||
line_draw_dsc.p2.x = 350
|
||||
line_draw_dsc.p2.y = 55
|
||||
lv.draw_line(layer, line_draw_dsc)
|
||||
|
||||
canvas.finish_layer(layer)
|
||||
|
||||
c = lv.color_hex(0xff0000)
|
||||
for i in range(50):
|
||||
canvas.set_px(100 + i * 2, 10, c, lv.OPA.COVER)
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def main():
|
||||
lv.tick_inc(300)
|
||||
lv.refr_now(None)
|
||||
|
||||
|
||||
test_event()
|
||||
create_ui()
|
||||
main()
|
||||
# end
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1 @@
|
||||
*_err.png
|
||||
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 22 KiB |