feat: added PicoW_Sensor code template
Credits to @ext-erich.styger that provided the template
This commit is contained in:
committed by
Sylvan Arnold
parent
b2e9eab44e
commit
6cd510e749
3
TSM_PicoW_Sensor/McuLib/LittlevGL/.gitignore
vendored
Normal file
3
TSM_PicoW_Sensor/McuLib/LittlevGL/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/CMakeFiles/
|
||||
Makefile
|
||||
*.a
|
||||
27
TSM_PicoW_Sensor/McuLib/LittlevGL/CMakeLists.txt
Normal file
27
TSM_PicoW_Sensor/McuLib/LittlevGL/CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
# file: Collect all files that need to be compiled.
|
||||
|
||||
# search recursively all files:
|
||||
file(GLOB_RECURSE LVGL_FILES "lvgl/src/*.c")
|
||||
|
||||
# add_library: With this declaration, you express the intent to build a library.
|
||||
# The first argument, is the name of the library,
|
||||
# the second argument are the files that will be compiled to create your library.
|
||||
add_library(lvglLib
|
||||
${LVGL_FILES}
|
||||
)
|
||||
|
||||
# target_link_libraries: If you link with other libraries, list them here
|
||||
target_link_libraries(
|
||||
lvglLib
|
||||
)
|
||||
|
||||
# target_include_directories: Libraries need to publish their header files
|
||||
# so that you can import them in source code. This statement expresses where to find the files
|
||||
# - typically in an include directory of your projects.
|
||||
target_include_directories(
|
||||
lvglLib
|
||||
PUBLIC
|
||||
./
|
||||
./lvgl
|
||||
)
|
||||
|
||||
786
TSM_PicoW_Sensor/McuLib/LittlevGL/lv_conf_template.h
Normal file
786
TSM_PicoW_Sensor/McuLib/LittlevGL/lv_conf_template.h
Normal file
@@ -0,0 +1,786 @@
|
||||
/**
|
||||
* @file lv_conf.h
|
||||
* Configuration file for v8.3.3
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copy this file as `lv_conf.h`
|
||||
* 1. simply next to the `lvgl` folder
|
||||
* 2. or any other places and
|
||||
* - define `LV_CONF_INCLUDE_SIMPLE`
|
||||
* - add the path as include path
|
||||
*/
|
||||
|
||||
/* clang-format off */
|
||||
#if 0 /*Set it to "1" to enable content*/
|
||||
|
||||
#ifndef LV_CONF_H
|
||||
#define LV_CONF_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*====================
|
||||
COLOR SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*Color depth: 1 (1 bit per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
|
||||
#define LV_COLOR_DEPTH 1
|
||||
|
||||
#define LV_HOR_RES (128)
|
||||
#define LV_VER_RES (64)
|
||||
/* default font: see LV_FONT_DEFAULT */
|
||||
//#define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_14 /* default
|
||||
|
||||
/*Enable features to draw on transparent background.
|
||||
*It's required if opa, and transform_* style properties are used.
|
||||
*Can be also used if the UI is above another layer, e.g. an OSD menu or video player.*/
|
||||
#define LV_COLOR_SCREEN_TRANSP 0
|
||||
|
||||
/* 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 */
|
||||
#define LV_COLOR_MIX_ROUND_OFS 0
|
||||
|
||||
/*Images pixels with this color will not be drawn if they are chroma keyed)*/
|
||||
#define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/
|
||||
|
||||
/*=========================
|
||||
STDLIB WRAPPER SETTINGS
|
||||
*=========================*/
|
||||
|
||||
/*Enable and configure the built-in memory manager*/
|
||||
#define LV_USE_BUILTIN_MALLOC 0
|
||||
#if LV_USE_BUILTIN_MALLOC
|
||||
/*Size of the memory available for `lv_malloc()` in bytes (>= 2kB)*/
|
||||
#define LV_MEM_SIZE (128U * 1024U) /*[bytes]*/
|
||||
|
||||
/*Size of the memory expand for `lv_malloc()` in bytes*/
|
||||
#define LV_MEM_POOL_EXPAND_SIZE 0
|
||||
|
||||
/*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
|
||||
#define LV_MEM_ADR 0 /*0: unused*/
|
||||
/*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
|
||||
#undef LV_MEM_POOL_INCLUDE
|
||||
#undef LV_MEM_POOL_ALLOC
|
||||
#endif
|
||||
#endif /*LV_USE_BUILTIN_MALLOC*/
|
||||
|
||||
/*Enable lv_memcpy_builtin, lv_memset_builtin, lv_strlen_builtin, lv_strncpy_builtin*/
|
||||
#define LV_USE_BUILTIN_MEMCPY 1
|
||||
|
||||
/*Enable and configure the built-in (v)snprintf */
|
||||
#define LV_USE_BUILTIN_SNPRINTF 1
|
||||
#if LV_USE_BUILTIN_SNPRINTF
|
||||
#define LV_SPRINTF_USE_FLOAT 0
|
||||
#endif /*LV_USE_BUILTIN_SNPRINTF*/
|
||||
|
||||
#define LV_STDIO_INCLUDE <stdint.h>
|
||||
#define LV_STRING_INCLUDE <stdint.h>
|
||||
#define LV_STDLIB_INCLUDE <stdint.h>
|
||||
#if LV_USE_BUILTIN_MALLOC
|
||||
#define LV_MALLOC lv_malloc_builtin
|
||||
#define LV_REALLOC lv_realloc_builtin
|
||||
#define LV_FREE lv_free_builtin
|
||||
#else
|
||||
#define LV_MEM_CUSTOM_INCLUDE "FreeRTOS.h"
|
||||
#define CONFIG_LV_MALLOC pvPortMalloc
|
||||
#define CONFIG_LV_REALLOC pvPortRealloc
|
||||
#define CONFIG_LV_FREE vPortFree
|
||||
#endif
|
||||
#define LV_MEMSET lv_memset_builtin
|
||||
#define LV_MEMCPY lv_memcpy_builtin
|
||||
#define LV_SNPRINTF lv_snprintf_builtin
|
||||
#define LV_VSNPRINTF lv_vsnprintf_builtin
|
||||
#define LV_STRLEN lv_strlen_builtin
|
||||
#define LV_STRNCPY lv_strncpy_builtin
|
||||
|
||||
/*====================
|
||||
HAL SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*Default display refresh period. LVG will redraw changed areas with this period time*/
|
||||
#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/
|
||||
|
||||
/*Input device read period in milliseconds*/
|
||||
#define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/
|
||||
|
||||
/*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()`)*/
|
||||
#define LV_TICK_CUSTOM 0
|
||||
#if LV_TICK_CUSTOM
|
||||
#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/
|
||||
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/
|
||||
#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)*/
|
||||
#define LV_DPI_DEF LV_CONFIG_DPI /*130*/ /*[px/inch]*/
|
||||
|
||||
/*========================
|
||||
* DRAW CONFIGURATION
|
||||
*========================*/
|
||||
|
||||
/*Enable the built in mask engine.
|
||||
*Required to draw shadow, rounded corners, circles, arc, skew lines, or any other masks*/
|
||||
#define LV_USE_DRAW_MASKS 1
|
||||
|
||||
#define LV_USE_DRAW_SW 1
|
||||
#if LV_USE_DRAW_SW
|
||||
|
||||
/*Enable complex draw engine.
|
||||
*Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/
|
||||
#define LV_DRAW_SW_COMPLEX 1
|
||||
|
||||
/* If a widget has `style_opa < 255` (not `bg_opa`, `text_opa` etc) or not NORMAL blend mode
|
||||
* it is buffered into a "simple" layer before rendering. The widget can be buffered in smaller chunks.
|
||||
* "Transformed layers" (if `transform_angle/zoom` are set) use larger buffers
|
||||
* and can't be drawn in chunks. */
|
||||
|
||||
/*The target buffer size for simple layer chunks.*/
|
||||
#define LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE (24 * 1024) /*[bytes]*/
|
||||
|
||||
/*Used if `LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated.*/
|
||||
#define LV_DRAW_SW_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024) /*[bytes]*/
|
||||
|
||||
/*Allow buffering some shadow calculation.
|
||||
*LV_DRAW_SW_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius`
|
||||
*Caching has LV_DRAW_SW_SHADOW_CACHE_SIZE^2 RAM cost*/
|
||||
#define LV_DRAW_SW_SHADOW_CACHE_SIZE 0
|
||||
|
||||
/* 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 */
|
||||
#define LV_DRAW_SW_CIRCLE_CACHE_SIZE 4
|
||||
|
||||
/*Default gradient buffer size.
|
||||
*When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again.
|
||||
*LV_DRAW_SW_GRADIENT_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.*/
|
||||
#define LV_DRAW_SW_GRADIENT_CACHE_DEF_SIZE 0
|
||||
|
||||
/*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display)
|
||||
*LV_DRAW_SW_GRADIENT_DITHER 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 */
|
||||
#define LV_DRAW_SW_GRADIENT_DITHER 0
|
||||
#if LV_DRAW_SW_GRADIENT_DITHER
|
||||
/*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)*/
|
||||
#define LV_DRAW_SW_GRADIENT_DITHER_ERROR_DIFFUSION 0
|
||||
#endif
|
||||
|
||||
/*Enable subpixel rendering*/
|
||||
#define LV_DRAW_SW_FONT_SUBPX 0
|
||||
#if LV_DRAW_SW_FONT_SUBPX
|
||||
/*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/
|
||||
#define LV_DRAW_SW_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Use SDL renderer API*/
|
||||
#define LV_USE_DRAW_SDL 0
|
||||
#if LV_USE_DRAW_SDL
|
||||
#define LV_DRAW_SDL_INCLUDE_PATH <SDL2/SDL.h>
|
||||
/*Texture cache size, 8MB by default*/
|
||||
#define LV_DRAW_SDL_LRU_SIZE (1024 * 1024 * 8)
|
||||
/*Custom blend mode for mask drawing, disable if you need to link with older SDL2 lib*/
|
||||
#define LV_DRAW_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6))
|
||||
#endif
|
||||
|
||||
/*=====================
|
||||
* GPU CONFIGURATION
|
||||
*=====================*/
|
||||
|
||||
/*Use Arm's 2D acceleration library Arm-2D */
|
||||
#define LV_USE_GPU_ARM2D 0
|
||||
|
||||
/*Use STM32's DMA2D (aka Chrom Art) GPU*/
|
||||
#define LV_USE_GPU_STM32_DMA2D 0
|
||||
#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"*/
|
||||
#define LV_GPU_DMA2D_CMSIS_INCLUDE
|
||||
#endif
|
||||
|
||||
/*Use GD32 IPA GPU
|
||||
* This adds support for Image Processing Accelerator on GD32F450 and GD32F470 series MCUs
|
||||
*
|
||||
* NOTE: IPA on GD32F450 has a bug where the fill operation overwrites data beyond the
|
||||
* framebuffer. This driver works around it by saving and restoring affected memory, but
|
||||
* this makes it not thread-safe. GD32F470 is not affected. */
|
||||
#define LV_USE_GPU_GD32_IPA 0
|
||||
|
||||
/*Use NXP's PXP GPU iMX RTxxx platforms*/
|
||||
#define LV_USE_GPU_NXP_PXP 0
|
||||
#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()
|
||||
*/
|
||||
#define LV_USE_GPU_NXP_PXP_AUTO_INIT 0
|
||||
#endif
|
||||
|
||||
/*Use NXP's VG-Lite GPU iMX RTxxx platforms*/
|
||||
#define LV_USE_GPU_NXP_VG_LITE 0
|
||||
|
||||
/*Use SWM341's DMA2D GPU*/
|
||||
#define LV_USE_GPU_SWM341_DMA2D 0
|
||||
#if LV_USE_GPU_SWM341_DMA2D
|
||||
#define LV_GPU_SWM341_DMA2D_INCLUDE "SWM341.h"
|
||||
#endif
|
||||
|
||||
/*=======================
|
||||
* FEATURE CONFIGURATION
|
||||
*=======================*/
|
||||
|
||||
/*-------------
|
||||
* Logging
|
||||
*-----------*/
|
||||
|
||||
/*Enable the log module*/
|
||||
#define LV_USE_LOG 0
|
||||
#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*/
|
||||
#define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
|
||||
|
||||
/*1: Print the log with 'printf';
|
||||
*0: User need to register a callback with `lv_log_register_print_cb()`*/
|
||||
#define LV_LOG_PRINTF 0
|
||||
|
||||
/*1: Enable print timestamp;
|
||||
*0: Disable print timestamp*/
|
||||
#define LV_LOG_USE_TIMESTAMP 1
|
||||
|
||||
/*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/
|
||||
#define LV_LOG_TRACE_MEM 1
|
||||
#define LV_LOG_TRACE_TIMER 1
|
||||
#define LV_LOG_TRACE_INDEV 1
|
||||
#define LV_LOG_TRACE_DISP_REFR 1
|
||||
#define LV_LOG_TRACE_EVENT 1
|
||||
#define LV_LOG_TRACE_OBJ_CREATE 1
|
||||
#define LV_LOG_TRACE_LAYOUT 1
|
||||
#define LV_LOG_TRACE_ANIM 1
|
||||
|
||||
#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*/
|
||||
#define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_STYLE 0 /*Check if the styles are properly initialized. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_MEM_INTEGRITY 0 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/
|
||||
#define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/
|
||||
|
||||
/*Add a custom handler when assert happens e.g. to restart the MCU*/
|
||||
#define LV_ASSERT_HANDLER_INCLUDE <stdint.h>
|
||||
#define LV_ASSERT_HANDLER while(1); /*Halt by default*/
|
||||
|
||||
/*-------------
|
||||
* Others
|
||||
*-----------*/
|
||||
|
||||
/*1: Show CPU usage and FPS count*/
|
||||
#define LV_USE_PERF_MONITOR 0
|
||||
#if LV_USE_PERF_MONITOR
|
||||
#define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT
|
||||
#endif
|
||||
|
||||
/*1: Show the used memory and the memory fragmentation
|
||||
* Requires `LV_USE_BUILTIN_MALLOC = 1`*/
|
||||
#define LV_USE_MEM_MONITOR 0
|
||||
#if LV_USE_MEM_MONITOR
|
||||
#define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT
|
||||
#endif
|
||||
|
||||
/*1: Draw random colored rectangles over the redrawn areas*/
|
||||
#define LV_USE_REFR_DEBUG 0
|
||||
|
||||
/*Maximum buffer size to allocate for rotation.
|
||||
*Only used if software rotation is enabled in the display driver.*/
|
||||
#define LV_DISP_ROT_MAX_BUF (10*1024)
|
||||
|
||||
#define LV_USE_USER_DATA 1
|
||||
|
||||
/*Garbage Collector settings
|
||||
*Used if lvgl is bound to higher level language and the memory is managed by that language*/
|
||||
#define LV_ENABLE_GC 0
|
||||
#if LV_ENABLE_GC != 0
|
||||
#define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/
|
||||
#endif /*LV_ENABLE_GC*/
|
||||
|
||||
/*Default image cache size. Image caching keeps some images opened.
|
||||
*If only the built-in image formats are used there is no real advantage of caching.
|
||||
*With other image decoders (e.g. PNG or JPG) caching save the continuous open/decode of images.
|
||||
*However the opened images consume additional RAM.
|
||||
*0: to disable caching*/
|
||||
#define LV_IMG_CACHE_DEF_SIZE 0
|
||||
|
||||
|
||||
/*Number of stops allowed per gradient. Increase this to allow more stops.
|
||||
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
||||
#define LV_GRADIENT_MAX_STOPS 2
|
||||
|
||||
/* 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 */
|
||||
#define LV_COLOR_MIX_ROUND_OFS 0
|
||||
|
||||
/*=====================
|
||||
* COMPILER SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*For big endian systems set to 1*/
|
||||
#define LV_BIG_ENDIAN_SYSTEM 0
|
||||
|
||||
/*Define a custom attribute to `lv_tick_inc` function*/
|
||||
#define LV_ATTRIBUTE_TICK_INC
|
||||
|
||||
/*Define a custom attribute to `lv_timer_handler` function*/
|
||||
#define LV_ATTRIBUTE_TIMER_HANDLER
|
||||
|
||||
/*Define a custom attribute to `lv_disp_flush_ready` function*/
|
||||
#define LV_ATTRIBUTE_FLUSH_READY
|
||||
|
||||
/*Required alignment size for buffers*/
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1
|
||||
|
||||
/*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)))*/
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
|
||||
/*Attribute to mark large constant arrays for example font's bitmaps*/
|
||||
#define LV_ATTRIBUTE_LARGE_CONST
|
||||
|
||||
/*Compiler prefix for a big array declaration in RAM*/
|
||||
#define LV_ATTRIBUTE_LARGE_RAM_ARRAY
|
||||
|
||||
/*Place performance critical functions into a faster memory (e.g RAM)*/
|
||||
#define LV_ATTRIBUTE_FAST_MEM
|
||||
|
||||
|
||||
/*Export integer constant to binding. This macro is used with constants in the form of LV_<CONST> that
|
||||
*should also appear on LVGL binding API such as Micropython.*/
|
||||
#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/
|
||||
|
||||
/*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/
|
||||
#define LV_USE_LARGE_COORD 0
|
||||
|
||||
/*==================
|
||||
* FONT USAGE
|
||||
*===================*/
|
||||
|
||||
/*Montserrat fonts with ASCII range and some symbols using bpp = 4
|
||||
*https://fonts.google.com/specimen/Montserrat*/
|
||||
#define LV_FONT_MONTSERRAT_8 1
|
||||
#define LV_FONT_MONTSERRAT_10 1
|
||||
#define LV_FONT_MONTSERRAT_12 1
|
||||
#define LV_FONT_MONTSERRAT_14 1
|
||||
#define LV_FONT_MONTSERRAT_16 0
|
||||
#define LV_FONT_MONTSERRAT_18 0
|
||||
#define LV_FONT_MONTSERRAT_20 0
|
||||
#define LV_FONT_MONTSERRAT_22 0
|
||||
#define LV_FONT_MONTSERRAT_24 0
|
||||
#define LV_FONT_MONTSERRAT_26 0
|
||||
#define LV_FONT_MONTSERRAT_28 0
|
||||
#define LV_FONT_MONTSERRAT_30 0
|
||||
#define LV_FONT_MONTSERRAT_32 0
|
||||
#define LV_FONT_MONTSERRAT_34 0
|
||||
#define LV_FONT_MONTSERRAT_36 0
|
||||
#define LV_FONT_MONTSERRAT_38 0
|
||||
#define LV_FONT_MONTSERRAT_40 0
|
||||
#define LV_FONT_MONTSERRAT_42 0
|
||||
#define LV_FONT_MONTSERRAT_44 0
|
||||
#define LV_FONT_MONTSERRAT_46 0
|
||||
#define LV_FONT_MONTSERRAT_48 0
|
||||
|
||||
/*Demonstrate special features*/
|
||||
#define LV_FONT_MONTSERRAT_12_SUBPX 0
|
||||
#define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/
|
||||
#define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, Persian letters and all their forms*/
|
||||
#define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/
|
||||
|
||||
/*Pixel perfect monospace fonts*/
|
||||
#define LV_FONT_UNSCII_8 0
|
||||
#define LV_FONT_UNSCII_16 0
|
||||
|
||||
/*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)*/
|
||||
#define LV_FONT_CUSTOM_DECLARE
|
||||
|
||||
/*Always set a default font*/
|
||||
#define LV_FONT_DEFAULT &lv_font_montserrat_14
|
||||
|
||||
/*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.*/
|
||||
#define LV_FONT_FMT_TXT_LARGE 0
|
||||
|
||||
/*Enables/disables support for compressed fonts.*/
|
||||
#define LV_USE_FONT_COMPRESSED 0
|
||||
|
||||
/*Enable drawing placeholders when glyph dsc is not found*/
|
||||
#define LV_USE_FONT_PLACEHOLDER 1
|
||||
|
||||
/*=================
|
||||
* 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
|
||||
*/
|
||||
#define LV_TXT_ENC LV_TXT_ENC_UTF8
|
||||
|
||||
/*Can break (wrap) texts on these chars*/
|
||||
#define LV_TXT_BREAK_CHARS " ,.;:-_)]}"
|
||||
|
||||
/*If a word is at least this long, will break wherever "prettiest"
|
||||
*To disable, set to a value <= 0*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_LEN 0
|
||||
|
||||
/*Minimum number of characters in a long word to put on a line before a break.
|
||||
*Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
|
||||
|
||||
/*Minimum number of characters in a long word to put on a line after a break.
|
||||
*Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
|
||||
|
||||
/*The control character to use for signalling text recoloring.*/
|
||||
#define LV_TXT_COLOR_CMD "#"
|
||||
|
||||
/*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts.
|
||||
*The direction will be processed according to the Unicode Bidirectional Algorithm:
|
||||
*https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/
|
||||
#define LV_USE_BIDI 0
|
||||
#if LV_USE_BIDI
|
||||
/*Set the default direction. Supported values:
|
||||
*`LV_BASE_DIR_LTR` Left-to-Right
|
||||
*`LV_BASE_DIR_RTL` Right-to-Left
|
||||
*`LV_BASE_DIR_AUTO` detect texts base direction*/
|
||||
#define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO
|
||||
#endif
|
||||
|
||||
/*Enable Arabic/Persian processing
|
||||
*In these languages characters should be replaced with an other form based on their position in the text*/
|
||||
#define LV_USE_ARABIC_PERSIAN_CHARS 0
|
||||
|
||||
/*==================
|
||||
* WIDGETS
|
||||
*================*/
|
||||
|
||||
/*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/
|
||||
|
||||
#define LV_USE_ANIMIMG 0
|
||||
|
||||
#define LV_USE_ARC 1
|
||||
|
||||
#define LV_USE_BAR 1
|
||||
|
||||
#define LV_USE_BTN 1
|
||||
|
||||
#define LV_USE_BTNMATRIX 1
|
||||
|
||||
#define LV_USE_CALENDAR 0
|
||||
#if LV_USE_CALENDAR
|
||||
#define LV_CALENDAR_WEEK_STARTS_MONDAY 0
|
||||
#if LV_CALENDAR_WEEK_STARTS_MONDAY
|
||||
#define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}
|
||||
#else
|
||||
#define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"}
|
||||
#endif
|
||||
|
||||
#define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
|
||||
#define LV_USE_CALENDAR_HEADER_ARROW 1
|
||||
#define LV_USE_CALENDAR_HEADER_DROPDOWN 1
|
||||
#endif /*LV_USE_CALENDAR*/
|
||||
|
||||
#define LV_USE_CANVAS 0
|
||||
|
||||
#define LV_USE_CHART 0
|
||||
|
||||
#define LV_USE_CHECKBOX 1
|
||||
|
||||
#define LV_USE_COLORWHEEL 0
|
||||
|
||||
#define LV_USE_DROPDOWN 1 /*Requires: lv_label*/
|
||||
|
||||
#define LV_USE_IMG 1 /*Requires: lv_label*/
|
||||
|
||||
#define LV_USE_IMGBTN 0
|
||||
|
||||
#define LV_USE_KEYBOARD 0
|
||||
|
||||
#define LV_USE_LABEL 1
|
||||
#if LV_USE_LABEL
|
||||
#define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/
|
||||
#define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/
|
||||
#endif
|
||||
|
||||
#define LV_USE_LED 0
|
||||
|
||||
#define LV_USE_LINE 1
|
||||
|
||||
#define LV_USE_LIST 0
|
||||
|
||||
#define LV_USE_MENU 0
|
||||
|
||||
#define LV_USE_METER 0
|
||||
|
||||
#define LV_USE_MSGBOX 0
|
||||
|
||||
#define LV_USE_ROLLER 1 /*Requires: lv_label*/
|
||||
|
||||
#define LV_USE_SLIDER 1 /*Requires: lv_bar*/
|
||||
|
||||
#define LV_USE_SPAN 0
|
||||
#if LV_USE_SPAN
|
||||
/*A line text can contain maximum num of span descriptor */
|
||||
#define LV_SPAN_SNIPPET_STACK_SIZE 64
|
||||
#endif
|
||||
|
||||
#define LV_USE_SPINBOX 0
|
||||
|
||||
#define LV_USE_SPINNER 0
|
||||
|
||||
#define LV_USE_SWITCH 1
|
||||
|
||||
#define LV_USE_TEXTAREA 1 /*Requires: lv_label*/
|
||||
#if LV_USE_TEXTAREA != 0
|
||||
#define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/
|
||||
#endif
|
||||
|
||||
#define LV_USE_TABLE 0
|
||||
|
||||
#define LV_USE_TABVIEW 0
|
||||
|
||||
#define LV_USE_TILEVIEW 0
|
||||
|
||||
#define LV_USE_WIN 0
|
||||
|
||||
/*==================
|
||||
* THEMES
|
||||
*==================*/
|
||||
|
||||
/*A simple, impressive and very complete theme*/
|
||||
#define LV_USE_THEME_DEFAULT 0
|
||||
#if LV_USE_THEME_DEFAULT
|
||||
|
||||
/*0: Light mode; 1: Dark mode*/
|
||||
#define LV_THEME_DEFAULT_DARK 0
|
||||
|
||||
/*1: Enable grow on press*/
|
||||
#define LV_THEME_DEFAULT_GROW 1
|
||||
|
||||
/*Default transition time in [ms]*/
|
||||
#define LV_THEME_DEFAULT_TRANSITION_TIME 80
|
||||
#endif /*LV_USE_THEME_DEFAULT*/
|
||||
|
||||
/*A very simple theme that is a good starting point for a custom theme*/
|
||||
#define LV_USE_THEME_BASIC 0
|
||||
|
||||
/*A theme designed for monochrome displays*/
|
||||
#define LV_USE_THEME_MONO 1
|
||||
|
||||
/*==================
|
||||
* LAYOUTS
|
||||
*==================*/
|
||||
|
||||
/*A layout similar to Flexbox in CSS.*/
|
||||
#define LV_USE_FLEX 1 /* 1 */
|
||||
|
||||
/*A layout similar to Grid in CSS.*/
|
||||
#define LV_USE_GRID 0
|
||||
|
||||
/*====================
|
||||
* 3RD PARTS LIBRARIES
|
||||
*====================*/
|
||||
|
||||
/*File system interfaces for common APIs */
|
||||
|
||||
/*API for fopen, fread, etc*/
|
||||
#define LV_USE_FS_STDIO 0
|
||||
#if LV_USE_FS_STDIO
|
||||
#define LV_FS_STDIO_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||
#define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*API for open, read, etc*/
|
||||
#define LV_USE_FS_POSIX 0
|
||||
#if LV_USE_FS_POSIX
|
||||
#define LV_FS_POSIX_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||
#define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*API for CreateFile, ReadFile, etc*/
|
||||
#define LV_USE_FS_WIN32 0
|
||||
#if LV_USE_FS_WIN32
|
||||
#define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||
#define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/
|
||||
#define LV_USE_FS_FATFS 0
|
||||
#if LV_USE_FS_FATFS
|
||||
#define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*PNG decoder library*/
|
||||
#define LV_USE_PNG 0
|
||||
|
||||
/*BMP decoder library*/
|
||||
#define LV_USE_BMP 0
|
||||
|
||||
/* JPG + split JPG decoder library.
|
||||
* Split JPG is a custom format optimized for embedded systems. */
|
||||
#define LV_USE_SJPG 0
|
||||
|
||||
/*GIF decoder library*/
|
||||
#define LV_USE_GIF 0
|
||||
|
||||
/*QR code library*/
|
||||
#define LV_USE_QRCODE 0
|
||||
|
||||
/*FreeType library*/
|
||||
#define LV_USE_FREETYPE 0
|
||||
#if LV_USE_FREETYPE
|
||||
/*Memory used by FreeType to cache characters [bytes]*/
|
||||
#define LV_FREETYPE_CACHE_SIZE (64 * 1024)
|
||||
|
||||
/*Let FreeType to use LVGL memory and file porting*/
|
||||
#define LV_FREETYPE_USE_LVGL_PORT 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 */
|
||||
#define LV_FREETYPE_SBIT_CACHE 0
|
||||
|
||||
/* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */
|
||||
/* (0:use system defaults) */
|
||||
#define LV_FREETYPE_CACHE_FT_FACES 4
|
||||
#define LV_FREETYPE_CACHE_FT_SIZES 4
|
||||
#endif
|
||||
|
||||
/* Built-in TTF decoder */
|
||||
#define LV_USE_TINY_TTF 0
|
||||
#if LV_USE_TINY_TTF
|
||||
/* Enable loading TTF data from files */
|
||||
#define LV_TINY_TTF_FILE_SUPPORT 0
|
||||
#endif
|
||||
|
||||
/*Rlottie library*/
|
||||
#define LV_USE_RLOTTIE 0
|
||||
|
||||
/*FFmpeg library for image decoding and playing videos
|
||||
*Supports all major image formats so do not enable other image decoder with it*/
|
||||
#define LV_USE_FFMPEG 0
|
||||
#if LV_USE_FFMPEG
|
||||
/*Dump input information to stderr*/
|
||||
#define LV_FFMPEG_DUMP_FORMAT 0
|
||||
#endif
|
||||
|
||||
/*-----------
|
||||
* Others
|
||||
*----------*/
|
||||
|
||||
/*1: Enable API to take snapshot for object*/
|
||||
#define LV_USE_SNAPSHOT 0
|
||||
|
||||
/*1: Enable Monkey test*/
|
||||
#define LV_USE_MONKEY 0
|
||||
|
||||
/*1: Enable grid navigation*/
|
||||
#define LV_USE_GRIDNAV 0
|
||||
|
||||
/*1: Enable lv_obj fragment*/
|
||||
#define LV_USE_FRAGMENT 0
|
||||
|
||||
/*1: Support using images as font in label or span widgets */
|
||||
#define LV_USE_IMGFONT 0
|
||||
|
||||
/*1: Enable a published subscriber based messaging system */
|
||||
#define LV_USE_MSG 0
|
||||
|
||||
/*1: Enable Pinyin input method*/
|
||||
/*Requires: lv_keyboard*/
|
||||
#define LV_USE_IME_PINYIN 0
|
||||
#if LV_USE_IME_PINYIN
|
||||
/*1: Use default thesaurus*/
|
||||
/*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/
|
||||
#define LV_IME_PINYIN_USE_DEFAULT_DICT 1
|
||||
/*Set the maximum number of candidate panels that can be displayed*/
|
||||
/*This needs to be adjusted according to the size of the screen*/
|
||||
#define LV_IME_PINYIN_CAND_TEXT_NUM 6
|
||||
|
||||
/*Use 9 key input(k9)*/
|
||||
#define LV_IME_PINYIN_USE_K9_MODE 1
|
||||
#if LV_IME_PINYIN_USE_K9_MODE == 1
|
||||
#define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3
|
||||
#endif // LV_IME_PINYIN_USE_K9_MODE
|
||||
#endif
|
||||
|
||||
/*==================
|
||||
* EXAMPLES
|
||||
*==================*/
|
||||
|
||||
/*Enable the examples to be built with the library*/
|
||||
#define LV_BUILD_EXAMPLES 0
|
||||
|
||||
/*===================
|
||||
* DEMO USAGE
|
||||
====================*/
|
||||
|
||||
/*Show some widget. It might be required to increase `LV_MEM_SIZE` */
|
||||
#define LV_USE_DEMO_WIDGETS 0
|
||||
#if LV_USE_DEMO_WIDGETS
|
||||
#define LV_DEMO_WIDGETS_SLIDESHOW 0
|
||||
#endif
|
||||
|
||||
/*Demonstrate the usage of encoder and keyboard*/
|
||||
#define LV_USE_DEMO_KEYPAD_AND_ENCODER 0
|
||||
|
||||
/*Benchmark your system*/
|
||||
#define LV_USE_DEMO_BENCHMARK 0
|
||||
#if LV_USE_DEMO_BENCHMARK
|
||||
/*Use RGB565A8 images with 16 bit color depth instead of ARGB8565*/
|
||||
#define LV_DEMO_BENCHMARK_RGB565A8 0
|
||||
#endif
|
||||
|
||||
/*Stress test for LVGL*/
|
||||
#define LV_USE_DEMO_STRESS 0
|
||||
|
||||
/*Music player demo*/
|
||||
#define LV_USE_DEMO_MUSIC 0
|
||||
#if LV_USE_DEMO_MUSIC
|
||||
#define LV_DEMO_MUSIC_SQUARE 0
|
||||
#define LV_DEMO_MUSIC_LANDSCAPE 0
|
||||
#define LV_DEMO_MUSIC_ROUND 0
|
||||
#define LV_DEMO_MUSIC_LARGE 0
|
||||
#define LV_DEMO_MUSIC_AUTO_PLAY 0
|
||||
#endif
|
||||
|
||||
/*--END OF LV_CONF_H--*/
|
||||
|
||||
#endif /*LV_CONF_H*/
|
||||
|
||||
#endif /*End of "Content enable"*/
|
||||
8
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/LICENCE.txt
Normal file
8
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/LICENCE.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
MIT licence
|
||||
Copyright (c) 2021 LVGL Kft
|
||||
|
||||
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.
|
||||
186
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/README.md
Normal file
186
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/README.md
Normal file
@@ -0,0 +1,186 @@
|
||||
<h1 align="center"> LVGL - Light and Versatile Graphics Library</h1>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://lvgl.io/assets/images/lvgl_widgets_demo.gif">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
LVGL provides everything you need to create an embedded GUI with easy-to-use graphical elements, beautiful visual effects and a low memory footprint.
|
||||
</p>
|
||||
|
||||
<h4 align="center">
|
||||
<a href="https://lvgl.io">Website </a> ·
|
||||
<a href="https://docs.lvgl.io/">Docs</a> ·
|
||||
<a href="https://forum.lvgl.io">Forum</a> ·
|
||||
<a href="https://lvgl.io/services">Services</a> ·
|
||||
<a href="https://docs.lvgl.io/master/examples.html">Interactive examples</a>
|
||||
</h4>
|
||||
|
||||
|
||||
**English** | [中文](./README_zh.md) | [Português do Brasil](./README_pt_BR.md)
|
||||
|
||||
|
||||
---
|
||||
|
||||
#### Table of content
|
||||
- [Overview](#overview)
|
||||
- [Get started](#get-started)
|
||||
- [Examples](#examples)
|
||||
- [Services](#services)
|
||||
- [Contributing](#contributing)
|
||||
|
||||
## Overview
|
||||
### Features
|
||||
* Powerful [building blocks](https://docs.lvgl.io/master/widgets/index.html): buttons, charts, lists, sliders, images, etc.
|
||||
* Advanced graphics engine: animations, anti-aliasing, opacity, smooth scrolling, blending modes, etc
|
||||
* Supports [various input devices](https://docs.lvgl.io/master/overview/indev.html): touchscreen, mouse, keyboard, encoder, buttons, etc.
|
||||
* Supports [multiple displays](https://docs.lvgl.io/master/overview/display.html)
|
||||
* Hardware independent, can be use with any microcontroller and display
|
||||
* Scalable to operate with little memory (64 kB Flash, 16 kB RAM)
|
||||
* Multi-language support with UTF-8 handling, CJK, Bidirectional and Arabic script support
|
||||
* Fully customizable graphical elements via [CSS-like styles](https://docs.lvgl.io/master/overview/style.html)
|
||||
* Powerful layouts inspired by CSS: [Flexbox](https://docs.lvgl.io/master/layouts/flex.html) and [Grid](https://docs.lvgl.io/master/layouts/grid.html)
|
||||
* OS, External memory and GPU are supported but not required. (built in support for STM32 DMA2D, SWM341 DMA2D, and NXP PXP and VGLite)
|
||||
* Smooth rendering even with a [single frame buffer](https://docs.lvgl.io/master/porting/display.html)
|
||||
* Written in C and compatible with C++
|
||||
* Micropython Binding exposes [LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings)
|
||||
* [Simulator](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) to develop on PC without embedded hardware
|
||||
* 100+ simple [Examples](https://github.com/lvgl/lvgl/tree/master/examples)
|
||||
* [Documentation](http://docs.lvgl.io/) and API references online and in PDF
|
||||
|
||||
### Requirements
|
||||
Basically, every modern controller (which is able to drive a display) is suitable to run LVGL. The minimal requirements are:
|
||||
<table>
|
||||
<tr>
|
||||
<td> <strong>Name</strong> </td>
|
||||
<td><strong>Minimal</strong></td>
|
||||
<td><strong>Recommended</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Architecture</strong></td>
|
||||
<td colspan="2">16, 32 or 64 bit microcontroller or processor</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> <strong>Clock</strong></td>
|
||||
<td> > 16 MHz </td>
|
||||
<td> > 48 MHz</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> <strong>Flash/ROM</strong></td>
|
||||
<td> > 64 kB </td>
|
||||
<td> > 180 kB</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> <strong>Static RAM</strong></td>
|
||||
<td> > 16 kB </td>
|
||||
<td> > 48 kB</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> <strong>Draw buffer</strong></td>
|
||||
<td> > 1 × <em>hor. res.</em> pixels </td>
|
||||
<td> > 1/10 screen size </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> <strong>Compiler</strong></td>
|
||||
<td colspan="2"> C99 or newer </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
*Note that the memory usage might vary depending on the architecture, compiler and build options.*
|
||||
|
||||
### Supported platforms
|
||||
LVGL is completely platform independent and can be used with any MCU that fulfills the requirements.
|
||||
Just to mention some platforms:
|
||||
- NXP: Kinetis, LPC, iMX, iMX RT
|
||||
- STM32F1, STM32F3, STM32F4, STM32F7, STM32L4, STM32L5, STM32H7
|
||||
- Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ
|
||||
- [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb)
|
||||
- [Raspberry Pi](https://github.com/lvgl/lv_port_linux_frame_buffer)
|
||||
- [Espressif ESP32](https://github.com/lvgl/lv_port_esp32)
|
||||
- [Infineon Aurix](https://github.com/lvgl/lv_port_aurix)
|
||||
- Nordic NRF52 Bluetooth modules
|
||||
- Quectel modems
|
||||
- [SYNWIT SWM341](http://www.synwit.cn/)
|
||||
|
||||
LVGL is also available as:
|
||||
- [Arduino library](https://docs.lvgl.io/master/get-started/platforms/arduino.html)
|
||||
- [PlatformIO package](https://registry.platformio.org/libraries/lvgl/lvgl)
|
||||
- [Zephyr library](https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_LVGL.html)
|
||||
- [ESP32 component](https://docs.lvgl.io/master/get-started/platforms/espressif.html)
|
||||
- [NXP MCUXpresso component](https://www.nxp.com/design/software/embedded-software/lvgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY)
|
||||
- [NuttX library](https://docs.lvgl.io/master/get-started/os/nuttx.html)
|
||||
- [RT-Thread RTOS](https://docs.lvgl.io/master/get-started/os/rt-thread.html)
|
||||
|
||||
|
||||
## Get started
|
||||
This list shows the recommended way of learning the library:
|
||||
1. Check the [Online demos](https://lvgl.io/demos) to see LVGL in action (3 minutes)
|
||||
2. Read the [Introduction](https://docs.lvgl.io/master/intro/index.html) page of the documentation (5 minutes)
|
||||
3. Get familiar with the basics on the [Quick overview](https://docs.lvgl.io/master/get-started/quick-overview.html) page (15 minutes)
|
||||
4. Set up a [Simulator](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) (10 minutes)
|
||||
5. Try out some [Examples](https://github.com/lvgl/lvgl/tree/master/examples)
|
||||
6. Port LVGL to a board. See the [Porting](https://docs.lvgl.io/master/porting/index.html) guide or check the ready to use [Projects](https://github.com/lvgl?q=lv_port_)
|
||||
7. Read the [Overview](https://docs.lvgl.io/master/overview/index.html) page to get a better understanding of the library (2-3 hours)
|
||||
8. Check the documentation of the [Widgets](https://docs.lvgl.io/master/widgets/index.html) to see their features and usage
|
||||
9. If you have questions go to the [Forum](http://forum.lvgl.io/)
|
||||
10. Read the [Contributing](https://docs.lvgl.io/master/CONTRIBUTING.html) guide to see how you can help to improve LVGL (15 minutes)
|
||||
|
||||
## Examples
|
||||
|
||||
For more examples see the [examples](https://github.com/lvgl/lvgl/tree/master/examples) folder.
|
||||
|
||||

|
||||
|
||||
### C
|
||||
```c
|
||||
lv_obj_t * btn = lv_btn_create(lv_scr_act()); /*Add a button to the current screen*/
|
||||
lv_obj_set_pos(btn, 10, 10); /*Set its position*/
|
||||
lv_obj_set_size(btn, 100, 50); /*Set its size*/
|
||||
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL); /*Assign a callback to the button*/
|
||||
|
||||
lv_obj_t * label = lv_label_create(btn); /*Add a label to the button*/
|
||||
lv_label_set_text(label, "Button"); /*Set the labels text*/
|
||||
lv_obj_center(label); /*Align the label to the center*/
|
||||
...
|
||||
|
||||
void btn_event_cb(lv_event_t * e)
|
||||
{
|
||||
printf("Clicked\n");
|
||||
}
|
||||
```
|
||||
### Micropython
|
||||
Learn more about [Micropython](https://docs.lvgl.io/master/get-started/bindings/micropython.html).
|
||||
```python
|
||||
def btn_event_cb(e):
|
||||
print("Clicked")
|
||||
|
||||
# Create a Button and a Label
|
||||
btn = lv.btn(lv.scr_act())
|
||||
btn.set_pos(10, 10)
|
||||
btn.set_size(100, 50)
|
||||
btn.add_event_cb(btn_event_cb, lv.EVENT.CLICKED, None)
|
||||
|
||||
label = lv.label(btn)
|
||||
label.set_text("Button")
|
||||
label.center()
|
||||
```
|
||||
|
||||
## Services
|
||||
LVGL Kft was established to provide a solid background for LVGL library. We offer several type of services to help you in UI development:
|
||||
- Graphics design
|
||||
- UI implementation
|
||||
- Consulting/Support
|
||||
|
||||
For more information see https://lvgl.io/services
|
||||
Feel free to contact us if you have any questions.
|
||||
|
||||
|
||||
## Contributing
|
||||
LVGL is an open project and contribution is very welcome. There are many ways to contribute from simply speaking about your project, through writing examples, improving the documentation, fixing bugs to hosting your own project under the LVGL organization.
|
||||
|
||||
For a detailed description of contribution opportunities visit the [Contributing](https://docs.lvgl.io/master/CONTRIBUTING.html) section of the documentation.
|
||||
|
||||
206
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/README_pt_BR.md
Normal file
206
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/README_pt_BR.md
Normal file
@@ -0,0 +1,206 @@
|
||||
<h1 align="center"> LVGL - Biblioteca gráfica leve e versátil</h1>
|
||||
<p align="center">
|
||||
<img src="https://lvgl.io/assets/images/lvgl_widgets_demo.gif">
|
||||
</p>
|
||||
<p align="center">
|
||||
O LVGL fornece tudo o que você precisa para criar uma GUI incorporada com elementos gráficos fáceis de usar, belos efeitos visuais e um baixo consumo de memória.
|
||||
</p>
|
||||
<h4 align="center">
|
||||
<a href="https://lvgl.io">Site</a> ·
|
||||
<a href="https://docs.lvgl.io/">Documentação</a> ·
|
||||
<a href="https://forum.lvgl.io">Fórum</a> ·
|
||||
<a href="https://lvgl.io/services">Serviços</a> ·
|
||||
<a href="https://docs.lvgl.io/master/examples.html">Exemplos interativos</a>
|
||||
</h4>
|
||||
|
||||
[English](./README.md) | [中文](./README_zh.md) | **Português do Brasil**
|
||||
|
||||
---
|
||||
|
||||
### Tabela de conteúdo
|
||||
|
||||
- [Visão Geral](#visão-geral)
|
||||
- [Iniciando](#iniciando)
|
||||
- [Exemplos](#exemplos)
|
||||
- [Serviços](#serviços)
|
||||
- [Contribuindo](#contribuindo)
|
||||
|
||||
## Visão Geral
|
||||
|
||||
### Recursos
|
||||
* Poderosos [widgets](https://docs.lvgl.io/master/widgets/index.html): botões, gráficos, listas, controles deslizantes (sliders), imagens, etc.
|
||||
* Mecanismo gráfico avançado: animações, anti-aliasing, opacidade, rolagem suave, modos de mesclagem (blending modes), etc.
|
||||
* Suporte à [vários dispositivos de entrada](https://docs.lvgl.io/master/overview/indev.html): tela sensível ao toque, mouse, teclado, codificador, botões, etc.
|
||||
* Suporte à [vários monitores](https://docs.lvgl.io/master/overview/display.html)
|
||||
* Pode ser usado com qualquer microcontrolador e display, independente do hardware
|
||||
* Escalável para operar com pouca memória (64 kB Flash, 16 kB RAM)
|
||||
* Suporte multilíngue com manipulação UTF-8, suporte ao alfabeto bidirecional, árabe e CJK (Chinês, Japonês e Coreano)
|
||||
* Elementos gráficos totalmente personalizáveis por meio de [CSS](https://docs.lvgl.io/master/overview/style.html)
|
||||
* Layouts poderosos inspirados em CSS: [Flexbox](https://docs.lvgl.io/master/layouts/flex.html) e [Grid](https://docs.lvgl.io/master/layouts/grid.html)
|
||||
* SO, memória externa e GPU são suportados, mas não obrigatórios. (suporte integrado para STM32 DMA2D, SWM341 DMA2D e NXP PXP e VGLite)
|
||||
* Renderização suave mesmo com um [buffer de quadro único](https://docs.lvgl.io/master/porting/display.html) (single frame buffer)
|
||||
* Escrito em C e compatível com C++
|
||||
* Uso do LittlevGL com Micropython simplificado com [LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings)
|
||||
* [Simulador](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) para desenvolver no PC sem hardware embutido
|
||||
* Mais de 100 [exemplos simples](https://github.com/lvgl/lvgl/tree/master/examples)
|
||||
* [Documentação](http://docs.lvgl.io/) e referências de API online e em PDF
|
||||
|
||||
### Requerimentos
|
||||
Basicamente, todo controlador moderno (que é capaz de acionar um display) é adequado para executar LVGL. Os requisitos mínimos são:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<strong>Nome</strong>
|
||||
</td>
|
||||
<td>
|
||||
<strong>Minímo</strong>
|
||||
</td>
|
||||
<td>
|
||||
<strong>Recomendado</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<strong>Arquitetura</strong>
|
||||
</td>
|
||||
<td colspan="2">Microcontrolador ou processador de 16, 32 ou 64 bits</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<strong>Clock</strong>
|
||||
</td>
|
||||
<td>> 16 MHz</td>
|
||||
<td>> 48 MHz</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<strong>Flash/ROM</strong>
|
||||
</td>
|
||||
<td>> 64 kB</td>
|
||||
<td>> 180 kB</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<strong>RAM estática</strong>
|
||||
</td>
|
||||
<td>> 16 kB</td>
|
||||
<td>> 48 kB</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<strong>Draw buffer</strong>
|
||||
</td>
|
||||
<td>> 1 × <em>hor. res.</em> pixels</td>
|
||||
<td>> tamanho da tela de 1/10</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<strong>Compilador</strong>
|
||||
</td>
|
||||
<td colspan="2">Padrão C99 ou mais recente</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
*Observe que o uso de memória pode variar dependendo da arquitetura, do compilador e das opções de compilação.*
|
||||
|
||||
### Plataformas suportadas
|
||||
O LVGL é completamente independente de plataforma e pode ser usado com qualquer MCU que atenda aos requisitos.
|
||||
Apenas para citar algumas plataformas:
|
||||
|
||||
- NXP: Kinetis, LPC, iMX, iMX RT
|
||||
- STM32F1, STM32F3, STM32F4, STM32F7, STM32L4, STM32L5, STM32H7
|
||||
- Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ
|
||||
- [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb)
|
||||
- [Raspberry Pi](http://www.vk3erw.com/index.php/16-software/63-raspberry-pi-official-7-touchscreen-and-littlevgl)
|
||||
- [Espressif ESP32](https://github.com/lvgl/lv_port_esp32)
|
||||
- [Infineon Aurix](https://github.com/lvgl/lv_port_aurix)
|
||||
- Nordic NRF52 Bluetooth modules
|
||||
- Quectel modems
|
||||
- [SYNWIT SWM341](https://www.synwit.cn/)
|
||||
|
||||
LVGL também está disponível para:
|
||||
- [Arduino library](https://docs.lvgl.io/master/get-started/platforms/arduino.html)
|
||||
- [PlatformIO package](https://registry.platformio.org/libraries/lvgl/lvgl)
|
||||
- [Zephyr library](https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_LVGL.html)
|
||||
- [ESP32 component](https://docs.lvgl.io/master/get-started/platforms/espressif.html)
|
||||
- [NXP MCUXpresso component](https://www.nxp.com/design/software/embedded-software/lvgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY)
|
||||
- [NuttX library](https://docs.lvgl.io/master/get-started/os/nuttx.html)
|
||||
- [RT-Thread RTOS](https://docs.lvgl.io/master/get-started/os/rt-thread.html)
|
||||
|
||||
## Iniciando
|
||||
Esta lista mostra a maneira recomendada de aprender sobre a biblioteca:
|
||||
|
||||
1. Confira as [demos on-line](https://lvgl.io/demos) para ver o LVGL em ação (3 minutos)
|
||||
2. Leia a [introdução](https://docs.lvgl.io/master/intro/index.html) da documentação (5 minutos)
|
||||
3. Familiarize-se com o básico da [Visão geral rápida](https://docs.lvgl.io/master/get-started/quick-overview.html) (15 minutos)
|
||||
4. Configure um [simulador](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) (10 minutos)
|
||||
5. Experimente alguns [Exemplos](https://github.com/lvgl/lvgl/tree/master/examples)
|
||||
6. Placa para porta LVGL. Veja o guia [porting](https://docs.lvgl.io/master/porting/index.html) ou verifique o pronto para usar [Projects](https://github.com/lvgl?q=lv_port_)
|
||||
7. Leia a [visão geral](https://docs.lvgl.io/master/overview/index.html) para entender melhor a biblioteca (2-3 horas)
|
||||
8. Verifique a documentação dos [widgets](https://docs.lvgl.io/master/widgets/index.html) para ver seus recursos e como utilizá-los
|
||||
9. Se você tiver dúvidas, acesse o [fórum](http://forum.lvgl.io/)
|
||||
10. Leia o guia de [contribuição](https://docs.lvgl.io/master/CONTRIBUTING.html) para ver como você pode ajudar a melhorar o LVGL (15 minutos)
|
||||
|
||||
## Exemplos
|
||||
Para mais exemplos, veja a pasta [examples](https://github.com/lvgl/lvgl/tree/master/examples).
|
||||
|
||||

|
||||
|
||||
### C
|
||||
|
||||
```c
|
||||
lv_obj_t * button = lv_btn_create(lv_scr_act()); /* Adiciona um botão à tela atual */
|
||||
lv_obj_set_pos(button, 10, 10); /* Define uma posição ao botão na tela */
|
||||
lv_obj_set_size(button, 100, 50); /* Define o tamanho */
|
||||
lv_obj_add_event_cb(button, button_event_callback, LV_EVENT_CLICKED, NULL); /* Atribui um retorno de chamada (callback) */
|
||||
|
||||
lv_obj_t * label = lv_label_create(button); /* Adiciona um rótulo (label) */
|
||||
lv_label_set_text(label, "Clique aqui"); /* Define o texto do rótulo (label) */
|
||||
lv_obj_center(label); /* Alinha o texto ao centro */
|
||||
...
|
||||
|
||||
void button_event_callback(lv_event_t * e)
|
||||
{
|
||||
printf("Clicado\n");
|
||||
}
|
||||
```
|
||||
|
||||
### Micropython
|
||||
Saiba mais em [Micropython](https://docs.lvgl.io/master/get-started/bindings/micropython.html)
|
||||
|
||||
```python
|
||||
def button_event_callback(event):
|
||||
print("Clicado")
|
||||
|
||||
# Cria um botão e um rótulo (label)
|
||||
button = lv.btn(lv.scr_act())
|
||||
button.set_pos(10, 10)
|
||||
button.set_size(100, 50)
|
||||
button.add_event_cb(button_event_callback, lv.EVENT.CLICKED, None)
|
||||
|
||||
label = lv.label(button)
|
||||
label.set_text("Cliquq aqui")
|
||||
label.center()
|
||||
```
|
||||
|
||||
## Serviços
|
||||
O LVGL Kft foi estabelecido para fornecer uma base sólida para a biblioteca LVGL. Oferecemos vários tipos de serviços
|
||||
para ajudá-lo no desenvolvimento da interface do usuário:
|
||||
|
||||
- Design gráfico
|
||||
- Implementação de IU
|
||||
- Consultoria/Suporte
|
||||
|
||||
Para mais informações, consulte [LVGL Serviços](https://lvgl.io/services). Sinta-se à vontade para entrar em contato
|
||||
conosco se tiver alguma dúvida.
|
||||
|
||||
## Contribuindo
|
||||
O LVGL é um projeto aberto e sua contribuição é muito bem-vinda. Há muitas maneiras de contribuir, desde simplesmente
|
||||
falando sobre seu projeto, escrevendo exemplos, melhorando a documentação, corrigindo bugs até hospedar seu próprio
|
||||
projeto sob a organização LVGL.
|
||||
|
||||
Para obter uma descrição detalhada das oportunidades de contribuição, visite a seção de [contribuição](https://docs.lvgl.io/master/CONTRIBUTING.html) da documentação.
|
||||
193
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/README_zh.md
Normal file
193
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/README_zh.md
Normal file
@@ -0,0 +1,193 @@
|
||||
<h1 align="center"> LVGL - Light and Versatile Graphics Library</h1>
|
||||
<h2 align="center"> LVGL - 轻量级通用型图形库</h2>
|
||||
|
||||
|
||||
|
||||
<p align="center">
|
||||
<img src="https://lvgl.io/assets/images/lvgl_widgets_demo.gif">
|
||||
</p>
|
||||
<p align="center">
|
||||
LVGL是一个高度可裁剪、低资源占用、界面美观且易用的嵌入式系统图形库
|
||||
</p>
|
||||
|
||||
|
||||
<h4 align="center">
|
||||
<a href="https://lvgl.io">官网</a> ·
|
||||
<a href="https://docs.lvgl.io/">文档</a> ·
|
||||
<a href="https://forum.lvgl.io">论坛</a> ·
|
||||
<a href="https://lvgl.io/services">服务</a> ·
|
||||
<a href="https://docs.lvgl.io/master/examples.html">例程</a>
|
||||
</h4>
|
||||
|
||||
|
||||
[English](./README.md) | **中文** | [Português do Brasil](./README_pt_BR.md)
|
||||
|
||||
|
||||
---
|
||||
|
||||
#### 目录
|
||||
- [概况与总览](#概况与总览)
|
||||
- [如何入门](#如何入门)
|
||||
- [例程](#例程)
|
||||
- [服务](#服务)
|
||||
- [如何向社区贡献](#如何向社区贡献)
|
||||
|
||||
## 概况与总览
|
||||
### 特性
|
||||
* 丰富且强大的模块化[图形组件](https://docs.lvgl.io/master/widgets/index.html):按钮 (buttons)、图表 (charts)、列表 (lists)、滑动条 (sliders)、图片 (images) 等
|
||||
* 高级的图形引擎:动画、抗锯齿、透明度、平滑滚动、图层混合等效果
|
||||
* 支持多种[输入设备](https://docs.lvgl.io/master/overview/indev.html):触摸屏、 键盘、编码器、按键等
|
||||
* 支持[多显示设备](https://docs.lvgl.io/master/overview/display.html)
|
||||
* 不依赖特定的硬件平台,可以在任何显示屏上运行
|
||||
* 配置可裁剪(最低资源占用:64 kB Flash,16 kB RAM)
|
||||
* 基于UTF-8的多语种支持,例如中文、日文、韩文、阿拉伯文等
|
||||
* 可以通过[类CSS](https://docs.lvgl.io/master/overview/style.html)的方式来设计、布局图形界面(例如:[Flexbox](https://docs.lvgl.io/master/layouts/flex.html)、[Grid](https://docs.lvgl.io/master/layouts/grid.html))
|
||||
* 支持操作系统、外置内存、以及硬件加速(LVGL已内建支持STM32 DMA2D、SWM341 DMA2D、NXP PXP和VGLite)
|
||||
* 即便仅有[单缓冲区(frame buffer)](https://docs.lvgl.io/master/porting/display.html)的情况下,也可保证渲染如丝般顺滑
|
||||
* 全部由C编写完成,并支持C++调用
|
||||
* 支持Micropython编程,参见:[LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings)
|
||||
* 支持[模拟器](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html)仿真,可以无硬件依托进行开发
|
||||
* 丰富详实的[例程](https://github.com/lvgl/lvgl/tree/master/examples)
|
||||
* 详尽的[文档](http://docs.lvgl.io/)以及API参考手册,可线上查阅或可下载为PDF格式
|
||||
|
||||
### 硬件要求
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td> <strong>要求</strong> </td>
|
||||
<td><strong>最低要求</strong></td>
|
||||
<td><strong>建议要求</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>架构</strong></td>
|
||||
<td colspan="2">16、32、64位微控制器或微处理器</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> <strong>时钟</strong></td>
|
||||
<td> > 16 MHz</td>
|
||||
<td> > 48 MHz</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> <strong>Flash/ROM</strong></td>
|
||||
<td> > 64 kB </td>
|
||||
<td> > 180 kB</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> <strong>Static RAM</strong></td>
|
||||
<td> > 16 kB </td>
|
||||
<td> > 48 kB</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> <strong>Draw buffer</strong></td>
|
||||
<td> > 1 × <em>hor. res.</em> pixels </td>
|
||||
<td> > 1/10屏幕大小 </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> <strong>编译器</strong></td>
|
||||
<td colspan="2"> C99或更新 </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
*注意:资源占用情况与具体硬件平台、编译器等因素有关,上表中仅给出参考值*
|
||||
|
||||
### 已经支持的平台
|
||||
LVGL本身并不依赖特定的硬件平台,任何满足LVGL硬件配置要求的微控制器均可运行LVGL。
|
||||
如下仅列举其中一部分:
|
||||
|
||||
- NXP: Kinetis, LPC, iMX, iMX RT
|
||||
- STM32F1, STM32F3, STM32F4, STM32F7, STM32L4, STM32L5, STM32H7
|
||||
- Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ
|
||||
- [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb)
|
||||
- [Raspberry Pi](http://www.vk3erw.com/index.php/16-software/63-raspberry-pi-official-7-touchscreen-and-littlevgl)
|
||||
- [Espressif ESP32](https://github.com/lvgl/lv_port_esp32)
|
||||
- [Infineon Aurix](https://github.com/lvgl/lv_port_aurix)
|
||||
- Nordic NRF52 Bluetooth modules
|
||||
- Quectel modems
|
||||
- [SYNWIT SWM341](https://www.synwit.cn/)
|
||||
|
||||
LVGL也支持:
|
||||
- [Arduino library](https://docs.lvgl.io/master/get-started/platforms/arduino.html)
|
||||
- [PlatformIO package](https://platformio.org/lib/show/12440/lvgl)
|
||||
- [Zephyr library](https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_LVGL.html)
|
||||
- [ESP32 component](https://docs.lvgl.io/master/get-started/platforms/espressif.html)
|
||||
- [NXP MCUXpresso component](https://www.nxp.com/design/software/embedded-software/lvgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY)
|
||||
- [NuttX library](https://docs.lvgl.io/master/get-started/os/nuttx.html)
|
||||
- [RT-Thread RTOS](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/packages-manual/lvgl-docs/introduction)
|
||||
|
||||
|
||||
## 如何入门
|
||||
请按照如下顺序来学习LVGL:
|
||||
1. 使用[网页在线例程](https://lvgl.io/demos)来体验LVGL(3分钟)
|
||||
2. 阅读文档[简介](https://docs.lvgl.io/master/intro/index.html)章节来初步了解LVGL(5分钟)
|
||||
3. 再来阅读一下文档快速[快速概览](https://docs.lvgl.io/master/get-started/quick-overview.html)章节来了解LVGL的基本知识(15分钟)
|
||||
4. 学习如何使用[模拟器](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html)来在电脑上仿真LVGL(10分钟)
|
||||
5. 试着动手实践一些[例程](https://github.com/lvgl/lvgl/tree/master/examples)
|
||||
6. 参考[移植指南](https://docs.lvgl.io/master/porting/index.html)尝试将LVGL移植到一块开发板上,LVGL也已经提供了一些移植好的[工程](https://github.com/lvgl?q=lv_port_)
|
||||
7. 仔细阅读文档[总览](https://docs.lvgl.io/master/overview/index.html)章节来更加深入的了解和熟悉LVGL(2-3小时)
|
||||
8. 浏览文档[组件(Widgets)](https://docs.lvgl.io/master/widgets/index.html)章节来了解如何使用它们
|
||||
9. 如果你有问题可以到LVGL[论坛](http://forum.lvgl.io/)提问
|
||||
10. 阅读文档[如何向社区贡献](https://docs.lvgl.io/master/CONTRIBUTING.html)章节来看看你能帮LVGL社区做些什么,以促进LVGL软件质量的不断提高(15分钟)
|
||||
|
||||
## 例程
|
||||
|
||||
更多例程请参见 [examples](https://github.com/lvgl/lvgl/tree/master/examples) 文件夹。
|
||||
|
||||

|
||||
|
||||
### C
|
||||
```c
|
||||
lv_obj_t * btn = lv_btn_create(lv_scr_act()); /*Add a button to the current screen*/
|
||||
lv_obj_set_pos(btn, 10, 10); /*Set its position*/
|
||||
lv_obj_set_size(btn, 100, 50); /*Set its size*/
|
||||
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL); /*Assign a callback to the button*/
|
||||
|
||||
lv_obj_t * label = lv_label_create(btn); /*Add a label to the button*/
|
||||
lv_label_set_text(label, "Button"); /*Set the labels text*/
|
||||
lv_obj_center(label); /*Align the label to the center*/
|
||||
...
|
||||
|
||||
void btn_event_cb(lv_event_t * e)
|
||||
{
|
||||
printf("Clicked\n");
|
||||
}
|
||||
```
|
||||
### Micropython
|
||||
更多信息请到 [Micropython官网](https://docs.lvgl.io/master/get-started/bindings/micropython.html) 查询.
|
||||
```python
|
||||
def btn_event_cb(e):
|
||||
print("Clicked")
|
||||
|
||||
# Create a Button and a Label
|
||||
btn = lv.btn(lv.scr_act())
|
||||
btn.set_pos(10, 10)
|
||||
btn.set_size(100, 50)
|
||||
btn.add_event_cb(btn_event_cb, lv.EVENT.CLICKED, None)
|
||||
|
||||
label = lv.label(btn)
|
||||
label.set_text("Button")
|
||||
label.center()
|
||||
```
|
||||
|
||||
## 服务
|
||||
LVGL 责任有限公司成立的目的是为了给用户使用LVGL图形库提供额外的技术支持,我们致力于提供以下服务:
|
||||
|
||||
- 图形设计
|
||||
- UI设计
|
||||
- 技术咨询以及技术支持
|
||||
|
||||
更多信息请参见 https://lvgl.io/services ,如果有任何问题请随时联系我们。
|
||||
|
||||
|
||||
## 如何向社区贡献
|
||||
LVGL是一个开源项目,非常欢迎您参与到社区贡献当中。您有很多种方式来为提高LVGL贡献您的一份力量,包括但不限于:
|
||||
|
||||
- 介绍你基于LVGL设计的作品或项目
|
||||
- 写一些例程
|
||||
- 修改以及完善文档
|
||||
- 修复bug
|
||||
|
||||
请参见文档[如何向社区贡献](https://docs.lvgl.io/master/CONTRIBUTING.html)章节来获取更多信息。
|
||||
759
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/lv_conf_template.h
Normal file
759
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/lv_conf_template.h
Normal file
@@ -0,0 +1,759 @@
|
||||
/**
|
||||
* @file lv_conf.h
|
||||
* Configuration file for v8.3.3
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copy this file as `lv_conf.h`
|
||||
* 1. simply next to the `lvgl` folder
|
||||
* 2. or any other places and
|
||||
* - define `LV_CONF_INCLUDE_SIMPLE`
|
||||
* - add the path as include path
|
||||
*/
|
||||
|
||||
/* clang-format off */
|
||||
#if 0 /*Set it to "1" to enable content*/
|
||||
|
||||
#ifndef LV_CONF_H
|
||||
#define LV_CONF_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*====================
|
||||
COLOR SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
|
||||
#define LV_COLOR_DEPTH 16
|
||||
|
||||
/*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/
|
||||
#define LV_COLOR_16_SWAP 0
|
||||
|
||||
/*Enable features to draw on transparent background.
|
||||
*It's required if opa, and transform_* style properties are used.
|
||||
*Can be also used if the UI is above another layer, e.g. an OSD menu or video player.*/
|
||||
#define LV_COLOR_SCREEN_TRANSP 0
|
||||
|
||||
/* 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 */
|
||||
#define LV_COLOR_MIX_ROUND_OFS 0
|
||||
|
||||
/*Images pixels with this color will not be drawn if they are chroma keyed)*/
|
||||
#define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/
|
||||
|
||||
/*=========================
|
||||
MEMORY SETTINGS
|
||||
*=========================*/
|
||||
|
||||
/*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/
|
||||
#define LV_MEM_CUSTOM 0
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
/*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
|
||||
#define LV_MEM_SIZE (48U * 1024U) /*[bytes]*/
|
||||
|
||||
/*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
|
||||
#define LV_MEM_ADR 0 /*0: unused*/
|
||||
/*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
|
||||
#undef LV_MEM_POOL_INCLUDE
|
||||
#undef LV_MEM_POOL_ALLOC
|
||||
#endif
|
||||
|
||||
#else /*LV_MEM_CUSTOM*/
|
||||
#define LV_MEM_CUSTOM_INCLUDE <stdlib.h> /*Header for the dynamic memory function*/
|
||||
#define LV_MEM_CUSTOM_ALLOC malloc
|
||||
#define LV_MEM_CUSTOM_FREE free
|
||||
#define LV_MEM_CUSTOM_REALLOC realloc
|
||||
#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. */
|
||||
#define LV_MEM_BUF_MAX_NUM 16
|
||||
|
||||
/*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/
|
||||
#define LV_MEMCPY_MEMSET_STD 0
|
||||
|
||||
/*====================
|
||||
HAL SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*Default display refresh period. LVG will redraw changed areas with this period time*/
|
||||
#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/
|
||||
|
||||
/*Input device read period in milliseconds*/
|
||||
#define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/
|
||||
|
||||
/*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()`)*/
|
||||
#define LV_TICK_CUSTOM 0
|
||||
#if LV_TICK_CUSTOM
|
||||
#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/
|
||||
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/
|
||||
#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)*/
|
||||
#define LV_DPI_DEF 130 /*[px/inch]*/
|
||||
|
||||
/*=======================
|
||||
* FEATURE CONFIGURATION
|
||||
*=======================*/
|
||||
|
||||
/*-------------
|
||||
* Drawing
|
||||
*-----------*/
|
||||
|
||||
/*Enable complex draw engine.
|
||||
*Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/
|
||||
#define LV_DRAW_COMPLEX 1
|
||||
#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*/
|
||||
#define LV_SHADOW_CACHE_SIZE 0
|
||||
|
||||
/* 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 */
|
||||
#define LV_CIRCLE_CACHE_SIZE 4
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
|
||||
/**
|
||||
* "Simple layers" are used when a widget has `style_opa < 255` to buffer the widget into a layer
|
||||
* and blend it as an image with the given opacity.
|
||||
* Note that `bg_opa`, `text_opa` etc don't require buffering into layer)
|
||||
* The widget can be buffered in smaller chunks to avoid using large buffers.
|
||||
*
|
||||
* - LV_LAYER_SIMPLE_BUF_SIZE: [bytes] the optimal target buffer size. LVGL will try to allocate it
|
||||
* - LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE: [bytes] used if `LV_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated.
|
||||
*
|
||||
* Both buffer sizes are in bytes.
|
||||
* "Transformed layers" (where transform_angle/zoom properties are used) use larger buffers
|
||||
* and can't be drawn in chunks. So these settings affects only widgets with opacity.
|
||||
*/
|
||||
#define LV_LAYER_SIMPLE_BUF_SIZE (24 * 1024)
|
||||
#define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024)
|
||||
|
||||
/*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*/
|
||||
#define LV_IMG_CACHE_DEF_SIZE 0
|
||||
|
||||
/*Number of stops allowed per gradient. Increase this to allow more stops.
|
||||
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
||||
#define LV_GRADIENT_MAX_STOPS 2
|
||||
|
||||
/*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.*/
|
||||
#define LV_GRAD_CACHE_DEF_SIZE 0
|
||||
|
||||
/*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 */
|
||||
#define LV_DITHER_GRADIENT 0
|
||||
#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)*/
|
||||
#define LV_DITHER_ERROR_DIFFUSION 0
|
||||
#endif
|
||||
|
||||
/*Maximum buffer size to allocate for rotation.
|
||||
*Only used if software rotation is enabled in the display driver.*/
|
||||
#define LV_DISP_ROT_MAX_BUF (10*1024)
|
||||
|
||||
/*-------------
|
||||
* GPU
|
||||
*-----------*/
|
||||
|
||||
/*Use Arm's 2D acceleration library Arm-2D */
|
||||
#define LV_USE_GPU_ARM2D 0
|
||||
|
||||
/*Use STM32's DMA2D (aka Chrom Art) GPU*/
|
||||
#define LV_USE_GPU_STM32_DMA2D 0
|
||||
#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"*/
|
||||
#define LV_GPU_DMA2D_CMSIS_INCLUDE
|
||||
#endif
|
||||
|
||||
/*Use SWM341's DMA2D GPU*/
|
||||
#define LV_USE_GPU_SWM341_DMA2D 0
|
||||
#if LV_USE_GPU_SWM341_DMA2D
|
||||
#define LV_GPU_SWM341_DMA2D_INCLUDE "SWM341.h"
|
||||
#endif
|
||||
|
||||
/*Use NXP's PXP GPU iMX RTxxx platforms*/
|
||||
#define LV_USE_GPU_NXP_PXP 0
|
||||
#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()
|
||||
*/
|
||||
#define LV_USE_GPU_NXP_PXP_AUTO_INIT 0
|
||||
#endif
|
||||
|
||||
/*Use NXP's VG-Lite GPU iMX RTxxx platforms*/
|
||||
#define LV_USE_GPU_NXP_VG_LITE 0
|
||||
|
||||
/*Use SDL renderer API*/
|
||||
#define LV_USE_GPU_SDL 0
|
||||
#if LV_USE_GPU_SDL
|
||||
#define LV_GPU_SDL_INCLUDE_PATH <SDL2/SDL.h>
|
||||
/*Texture cache size, 8MB by default*/
|
||||
#define LV_GPU_SDL_LRU_SIZE (1024 * 1024 * 8)
|
||||
/*Custom blend mode for mask drawing, disable if you need to link with older SDL2 lib*/
|
||||
#define LV_GPU_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6))
|
||||
#endif
|
||||
|
||||
/*-------------
|
||||
* Logging
|
||||
*-----------*/
|
||||
|
||||
/*Enable the log module*/
|
||||
#define LV_USE_LOG 0
|
||||
#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*/
|
||||
#define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
|
||||
|
||||
/*1: Print the log with 'printf';
|
||||
*0: User need to register a callback with `lv_log_register_print_cb()`*/
|
||||
#define LV_LOG_PRINTF 0
|
||||
|
||||
/*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/
|
||||
#define LV_LOG_TRACE_MEM 1
|
||||
#define LV_LOG_TRACE_TIMER 1
|
||||
#define LV_LOG_TRACE_INDEV 1
|
||||
#define LV_LOG_TRACE_DISP_REFR 1
|
||||
#define LV_LOG_TRACE_EVENT 1
|
||||
#define LV_LOG_TRACE_OBJ_CREATE 1
|
||||
#define LV_LOG_TRACE_LAYOUT 1
|
||||
#define LV_LOG_TRACE_ANIM 1
|
||||
|
||||
#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*/
|
||||
#define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_STYLE 0 /*Check if the styles are properly initialized. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_MEM_INTEGRITY 0 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/
|
||||
#define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/
|
||||
|
||||
/*Add a custom handler when assert happens e.g. to restart the MCU*/
|
||||
#define LV_ASSERT_HANDLER_INCLUDE <stdint.h>
|
||||
#define LV_ASSERT_HANDLER while(1); /*Halt by default*/
|
||||
|
||||
/*-------------
|
||||
* Others
|
||||
*-----------*/
|
||||
|
||||
/*1: Show CPU usage and FPS count*/
|
||||
#define LV_USE_PERF_MONITOR 0
|
||||
#if LV_USE_PERF_MONITOR
|
||||
#define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT
|
||||
#endif
|
||||
|
||||
/*1: Show the used memory and the memory fragmentation
|
||||
* Requires LV_MEM_CUSTOM = 0*/
|
||||
#define LV_USE_MEM_MONITOR 0
|
||||
#if LV_USE_MEM_MONITOR
|
||||
#define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT
|
||||
#endif
|
||||
|
||||
/*1: Draw random colored rectangles over the redrawn areas*/
|
||||
#define LV_USE_REFR_DEBUG 0
|
||||
|
||||
/*Change the built in (v)snprintf functions*/
|
||||
#define LV_SPRINTF_CUSTOM 0
|
||||
#if LV_SPRINTF_CUSTOM
|
||||
#define LV_SPRINTF_INCLUDE <stdio.h>
|
||||
#define lv_snprintf snprintf
|
||||
#define lv_vsnprintf vsnprintf
|
||||
#else /*LV_SPRINTF_CUSTOM*/
|
||||
#define LV_SPRINTF_USE_FLOAT 0
|
||||
#endif /*LV_SPRINTF_CUSTOM*/
|
||||
|
||||
#define LV_USE_USER_DATA 1
|
||||
|
||||
/*Garbage Collector settings
|
||||
*Used if lvgl is bound to higher level language and the memory is managed by that language*/
|
||||
#define LV_ENABLE_GC 0
|
||||
#if LV_ENABLE_GC != 0
|
||||
#define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/
|
||||
#endif /*LV_ENABLE_GC*/
|
||||
|
||||
/*=====================
|
||||
* COMPILER SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*For big endian systems set to 1*/
|
||||
#define LV_BIG_ENDIAN_SYSTEM 0
|
||||
|
||||
/*Define a custom attribute to `lv_tick_inc` function*/
|
||||
#define LV_ATTRIBUTE_TICK_INC
|
||||
|
||||
/*Define a custom attribute to `lv_timer_handler` function*/
|
||||
#define LV_ATTRIBUTE_TIMER_HANDLER
|
||||
|
||||
/*Define a custom attribute to `lv_disp_flush_ready` function*/
|
||||
#define LV_ATTRIBUTE_FLUSH_READY
|
||||
|
||||
/*Required alignment size for buffers*/
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1
|
||||
|
||||
/*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)))*/
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
|
||||
/*Attribute to mark large constant arrays for example font's bitmaps*/
|
||||
#define LV_ATTRIBUTE_LARGE_CONST
|
||||
|
||||
/*Compiler prefix for a big array declaration in RAM*/
|
||||
#define LV_ATTRIBUTE_LARGE_RAM_ARRAY
|
||||
|
||||
/*Place performance critical functions into a faster memory (e.g RAM)*/
|
||||
#define LV_ATTRIBUTE_FAST_MEM
|
||||
|
||||
/*Prefix variables that are used in GPU accelerated operations, often these need to be placed in RAM sections that are DMA accessible*/
|
||||
#define LV_ATTRIBUTE_DMA
|
||||
|
||||
/*Export integer constant to binding. This macro is used with constants in the form of LV_<CONST> that
|
||||
*should also appear on LVGL binding API such as Micropython.*/
|
||||
#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/
|
||||
|
||||
/*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/
|
||||
#define LV_USE_LARGE_COORD 0
|
||||
|
||||
/*==================
|
||||
* FONT USAGE
|
||||
*===================*/
|
||||
|
||||
/*Montserrat fonts with ASCII range and some symbols using bpp = 4
|
||||
*https://fonts.google.com/specimen/Montserrat*/
|
||||
#define LV_FONT_MONTSERRAT_8 0
|
||||
#define LV_FONT_MONTSERRAT_10 0
|
||||
#define LV_FONT_MONTSERRAT_12 0
|
||||
#define LV_FONT_MONTSERRAT_14 1
|
||||
#define LV_FONT_MONTSERRAT_16 0
|
||||
#define LV_FONT_MONTSERRAT_18 0
|
||||
#define LV_FONT_MONTSERRAT_20 0
|
||||
#define LV_FONT_MONTSERRAT_22 0
|
||||
#define LV_FONT_MONTSERRAT_24 0
|
||||
#define LV_FONT_MONTSERRAT_26 0
|
||||
#define LV_FONT_MONTSERRAT_28 0
|
||||
#define LV_FONT_MONTSERRAT_30 0
|
||||
#define LV_FONT_MONTSERRAT_32 0
|
||||
#define LV_FONT_MONTSERRAT_34 0
|
||||
#define LV_FONT_MONTSERRAT_36 0
|
||||
#define LV_FONT_MONTSERRAT_38 0
|
||||
#define LV_FONT_MONTSERRAT_40 0
|
||||
#define LV_FONT_MONTSERRAT_42 0
|
||||
#define LV_FONT_MONTSERRAT_44 0
|
||||
#define LV_FONT_MONTSERRAT_46 0
|
||||
#define LV_FONT_MONTSERRAT_48 0
|
||||
|
||||
/*Demonstrate special features*/
|
||||
#define LV_FONT_MONTSERRAT_12_SUBPX 0
|
||||
#define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/
|
||||
#define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, Persian letters and all their forms*/
|
||||
#define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/
|
||||
|
||||
/*Pixel perfect monospace fonts*/
|
||||
#define LV_FONT_UNSCII_8 0
|
||||
#define LV_FONT_UNSCII_16 0
|
||||
|
||||
/*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)*/
|
||||
#define LV_FONT_CUSTOM_DECLARE
|
||||
|
||||
/*Always set a default font*/
|
||||
#define LV_FONT_DEFAULT &lv_font_montserrat_14
|
||||
|
||||
/*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.*/
|
||||
#define LV_FONT_FMT_TXT_LARGE 0
|
||||
|
||||
/*Enables/disables support for compressed fonts.*/
|
||||
#define LV_USE_FONT_COMPRESSED 0
|
||||
|
||||
/*Enable subpixel rendering*/
|
||||
#define LV_USE_FONT_SUBPX 0
|
||||
#if LV_USE_FONT_SUBPX
|
||||
/*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/
|
||||
#define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/
|
||||
#endif
|
||||
|
||||
/*Enable drawing placeholders when glyph dsc is not found*/
|
||||
#define LV_USE_FONT_PLACEHOLDER 1
|
||||
|
||||
/*=================
|
||||
* 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
|
||||
*/
|
||||
#define LV_TXT_ENC LV_TXT_ENC_UTF8
|
||||
|
||||
/*Can break (wrap) texts on these chars*/
|
||||
#define LV_TXT_BREAK_CHARS " ,.;:-_"
|
||||
|
||||
/*If a word is at least this long, will break wherever "prettiest"
|
||||
*To disable, set to a value <= 0*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_LEN 0
|
||||
|
||||
/*Minimum number of characters in a long word to put on a line before a break.
|
||||
*Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
|
||||
|
||||
/*Minimum number of characters in a long word to put on a line after a break.
|
||||
*Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
|
||||
|
||||
/*The control character to use for signalling text recoloring.*/
|
||||
#define LV_TXT_COLOR_CMD "#"
|
||||
|
||||
/*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts.
|
||||
*The direction will be processed according to the Unicode Bidirectional Algorithm:
|
||||
*https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/
|
||||
#define LV_USE_BIDI 0
|
||||
#if LV_USE_BIDI
|
||||
/*Set the default direction. Supported values:
|
||||
*`LV_BASE_DIR_LTR` Left-to-Right
|
||||
*`LV_BASE_DIR_RTL` Right-to-Left
|
||||
*`LV_BASE_DIR_AUTO` detect texts base direction*/
|
||||
#define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO
|
||||
#endif
|
||||
|
||||
/*Enable Arabic/Persian processing
|
||||
*In these languages characters should be replaced with an other form based on their position in the text*/
|
||||
#define LV_USE_ARABIC_PERSIAN_CHARS 0
|
||||
|
||||
/*==================
|
||||
* WIDGET USAGE
|
||||
*================*/
|
||||
|
||||
/*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/
|
||||
|
||||
#define LV_USE_ARC 1
|
||||
|
||||
#define LV_USE_BAR 1
|
||||
|
||||
#define LV_USE_BTN 1
|
||||
|
||||
#define LV_USE_BTNMATRIX 1
|
||||
|
||||
#define LV_USE_CANVAS 1
|
||||
|
||||
#define LV_USE_CHECKBOX 1
|
||||
|
||||
#define LV_USE_DROPDOWN 1 /*Requires: lv_label*/
|
||||
|
||||
#define LV_USE_IMG 1 /*Requires: lv_label*/
|
||||
|
||||
#define LV_USE_LABEL 1
|
||||
#if LV_USE_LABEL
|
||||
#define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/
|
||||
#define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/
|
||||
#endif
|
||||
|
||||
#define LV_USE_LINE 1
|
||||
|
||||
#define LV_USE_ROLLER 1 /*Requires: lv_label*/
|
||||
#if LV_USE_ROLLER
|
||||
#define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/
|
||||
#endif
|
||||
|
||||
#define LV_USE_SLIDER 1 /*Requires: lv_bar*/
|
||||
|
||||
#define LV_USE_SWITCH 1
|
||||
|
||||
#define LV_USE_TEXTAREA 1 /*Requires: lv_label*/
|
||||
#if LV_USE_TEXTAREA != 0
|
||||
#define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/
|
||||
#endif
|
||||
|
||||
#define LV_USE_TABLE 1
|
||||
|
||||
/*==================
|
||||
* EXTRA COMPONENTS
|
||||
*==================*/
|
||||
|
||||
/*-----------
|
||||
* Widgets
|
||||
*----------*/
|
||||
#define LV_USE_ANIMIMG 1
|
||||
|
||||
#define LV_USE_CALENDAR 1
|
||||
#if LV_USE_CALENDAR
|
||||
#define LV_CALENDAR_WEEK_STARTS_MONDAY 0
|
||||
#if LV_CALENDAR_WEEK_STARTS_MONDAY
|
||||
#define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}
|
||||
#else
|
||||
#define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"}
|
||||
#endif
|
||||
|
||||
#define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
|
||||
#define LV_USE_CALENDAR_HEADER_ARROW 1
|
||||
#define LV_USE_CALENDAR_HEADER_DROPDOWN 1
|
||||
#endif /*LV_USE_CALENDAR*/
|
||||
|
||||
#define LV_USE_CHART 1
|
||||
|
||||
#define LV_USE_COLORWHEEL 1
|
||||
|
||||
#define LV_USE_IMGBTN 1
|
||||
|
||||
#define LV_USE_KEYBOARD 1
|
||||
|
||||
#define LV_USE_LED 1
|
||||
|
||||
#define LV_USE_LIST 1
|
||||
|
||||
#define LV_USE_MENU 1
|
||||
|
||||
#define LV_USE_METER 1
|
||||
|
||||
#define LV_USE_MSGBOX 1
|
||||
|
||||
#define LV_USE_SPAN 1
|
||||
#if LV_USE_SPAN
|
||||
/*A line text can contain maximum num of span descriptor */
|
||||
#define LV_SPAN_SNIPPET_STACK_SIZE 64
|
||||
#endif
|
||||
|
||||
#define LV_USE_SPINBOX 1
|
||||
|
||||
#define LV_USE_SPINNER 1
|
||||
|
||||
#define LV_USE_TABVIEW 1
|
||||
|
||||
#define LV_USE_TILEVIEW 1
|
||||
|
||||
#define LV_USE_WIN 1
|
||||
|
||||
/*-----------
|
||||
* Themes
|
||||
*----------*/
|
||||
|
||||
/*A simple, impressive and very complete theme*/
|
||||
#define LV_USE_THEME_DEFAULT 1
|
||||
#if LV_USE_THEME_DEFAULT
|
||||
|
||||
/*0: Light mode; 1: Dark mode*/
|
||||
#define LV_THEME_DEFAULT_DARK 0
|
||||
|
||||
/*1: Enable grow on press*/
|
||||
#define LV_THEME_DEFAULT_GROW 1
|
||||
|
||||
/*Default transition time in [ms]*/
|
||||
#define LV_THEME_DEFAULT_TRANSITION_TIME 80
|
||||
#endif /*LV_USE_THEME_DEFAULT*/
|
||||
|
||||
/*A very simple theme that is a good starting point for a custom theme*/
|
||||
#define LV_USE_THEME_BASIC 1
|
||||
|
||||
/*A theme designed for monochrome displays*/
|
||||
#define LV_USE_THEME_MONO 1
|
||||
|
||||
/*-----------
|
||||
* Layouts
|
||||
*----------*/
|
||||
|
||||
/*A layout similar to Flexbox in CSS.*/
|
||||
#define LV_USE_FLEX 1
|
||||
|
||||
/*A layout similar to Grid in CSS.*/
|
||||
#define LV_USE_GRID 1
|
||||
|
||||
/*---------------------
|
||||
* 3rd party libraries
|
||||
*--------------------*/
|
||||
|
||||
/*File system interfaces for common APIs */
|
||||
|
||||
/*API for fopen, fread, etc*/
|
||||
#define LV_USE_FS_STDIO 0
|
||||
#if LV_USE_FS_STDIO
|
||||
#define LV_FS_STDIO_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||
#define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*API for open, read, etc*/
|
||||
#define LV_USE_FS_POSIX 0
|
||||
#if LV_USE_FS_POSIX
|
||||
#define LV_FS_POSIX_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||
#define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*API for CreateFile, ReadFile, etc*/
|
||||
#define LV_USE_FS_WIN32 0
|
||||
#if LV_USE_FS_WIN32
|
||||
#define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||
#define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/
|
||||
#define LV_USE_FS_FATFS 0
|
||||
#if LV_USE_FS_FATFS
|
||||
#define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*PNG decoder library*/
|
||||
#define LV_USE_PNG 0
|
||||
|
||||
/*BMP decoder library*/
|
||||
#define LV_USE_BMP 0
|
||||
|
||||
/* JPG + split JPG decoder library.
|
||||
* Split JPG is a custom format optimized for embedded systems. */
|
||||
#define LV_USE_SJPG 0
|
||||
|
||||
/*GIF decoder library*/
|
||||
#define LV_USE_GIF 0
|
||||
|
||||
/*QR code library*/
|
||||
#define LV_USE_QRCODE 0
|
||||
|
||||
/*FreeType library*/
|
||||
#define LV_USE_FREETYPE 0
|
||||
#if LV_USE_FREETYPE
|
||||
/*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/
|
||||
#define LV_FREETYPE_CACHE_SIZE (16 * 1024)
|
||||
#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 */
|
||||
#define LV_FREETYPE_SBIT_CACHE 0
|
||||
/* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */
|
||||
/* (0:use system defaults) */
|
||||
#define LV_FREETYPE_CACHE_FT_FACES 0
|
||||
#define LV_FREETYPE_CACHE_FT_SIZES 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Rlottie library*/
|
||||
#define LV_USE_RLOTTIE 0
|
||||
|
||||
/*FFmpeg library for image decoding and playing videos
|
||||
*Supports all major image formats so do not enable other image decoder with it*/
|
||||
#define LV_USE_FFMPEG 0
|
||||
#if LV_USE_FFMPEG
|
||||
/*Dump input information to stderr*/
|
||||
#define LV_FFMPEG_DUMP_FORMAT 0
|
||||
#endif
|
||||
|
||||
/*-----------
|
||||
* Others
|
||||
*----------*/
|
||||
|
||||
/*1: Enable API to take snapshot for object*/
|
||||
#define LV_USE_SNAPSHOT 0
|
||||
|
||||
/*1: Enable Monkey test*/
|
||||
#define LV_USE_MONKEY 0
|
||||
|
||||
/*1: Enable grid navigation*/
|
||||
#define LV_USE_GRIDNAV 0
|
||||
|
||||
/*1: Enable lv_obj fragment*/
|
||||
#define LV_USE_FRAGMENT 0
|
||||
|
||||
/*1: Support using images as font in label or span widgets */
|
||||
#define LV_USE_IMGFONT 0
|
||||
|
||||
/*1: Enable a published subscriber based messaging system */
|
||||
#define LV_USE_MSG 0
|
||||
|
||||
/*1: Enable Pinyin input method*/
|
||||
/*Requires: lv_keyboard*/
|
||||
#define LV_USE_IME_PINYIN 0
|
||||
#if LV_USE_IME_PINYIN
|
||||
/*1: Use default thesaurus*/
|
||||
/*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/
|
||||
#define LV_IME_PINYIN_USE_DEFAULT_DICT 1
|
||||
/*Set the maximum number of candidate panels that can be displayed*/
|
||||
/*This needs to be adjusted according to the size of the screen*/
|
||||
#define LV_IME_PINYIN_CAND_TEXT_NUM 6
|
||||
|
||||
/*Use 9 key input(k9)*/
|
||||
#define LV_IME_PINYIN_USE_K9_MODE 1
|
||||
#if LV_IME_PINYIN_USE_K9_MODE == 1
|
||||
#define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3
|
||||
#endif // LV_IME_PINYIN_USE_K9_MODE
|
||||
#endif
|
||||
|
||||
/*==================
|
||||
* EXAMPLES
|
||||
*==================*/
|
||||
|
||||
/*Enable the examples to be built with the library*/
|
||||
#define LV_BUILD_EXAMPLES 1
|
||||
|
||||
/*===================
|
||||
* DEMO USAGE
|
||||
====================*/
|
||||
|
||||
/*Show some widget. It might be required to increase `LV_MEM_SIZE` */
|
||||
#define LV_USE_DEMO_WIDGETS 0
|
||||
#if LV_USE_DEMO_WIDGETS
|
||||
#define LV_DEMO_WIDGETS_SLIDESHOW 0
|
||||
#endif
|
||||
|
||||
/*Demonstrate the usage of encoder and keyboard*/
|
||||
#define LV_USE_DEMO_KEYPAD_AND_ENCODER 0
|
||||
|
||||
/*Benchmark your system*/
|
||||
#define LV_USE_DEMO_BENCHMARK 0
|
||||
#if LV_USE_DEMO_BENCHMARK
|
||||
/*Use RGB565A8 images with 16 bit color depth instead of ARGB8565*/
|
||||
#define LV_DEMO_BENCHMARK_RGB565A8 0
|
||||
#endif
|
||||
|
||||
/*Stress test for LVGL*/
|
||||
#define LV_USE_DEMO_STRESS 0
|
||||
|
||||
/*Music player demo*/
|
||||
#define LV_USE_DEMO_MUSIC 0
|
||||
#if LV_USE_DEMO_MUSIC
|
||||
#define LV_DEMO_MUSIC_SQUARE 0
|
||||
#define LV_DEMO_MUSIC_LANDSCAPE 0
|
||||
#define LV_DEMO_MUSIC_ROUND 0
|
||||
#define LV_DEMO_MUSIC_LARGE 0
|
||||
#define LV_DEMO_MUSIC_AUTO_PLAY 0
|
||||
#endif
|
||||
|
||||
/*--END OF LV_CONF_H--*/
|
||||
|
||||
#endif /*LV_CONF_H*/
|
||||
|
||||
#endif /*End of "Content enable"*/
|
||||
138
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/lvgl.h
Normal file
138
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/lvgl.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* @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 3
|
||||
#define LVGL_VERSION_PATCH 3
|
||||
#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"
|
||||
|
||||
/*********************
|
||||
* 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*/
|
||||
20
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_core.mk
Normal file
20
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_core.mk
Normal file
@@ -0,0 +1,20 @@
|
||||
CSRCS += lv_disp.c
|
||||
CSRCS += lv_group.c
|
||||
CSRCS += lv_indev.c
|
||||
CSRCS += lv_indev_scroll.c
|
||||
CSRCS += lv_obj.c
|
||||
CSRCS += lv_obj_class.c
|
||||
CSRCS += lv_obj_draw.c
|
||||
CSRCS += lv_obj_pos.c
|
||||
CSRCS += lv_obj_scroll.c
|
||||
CSRCS += lv_obj_style.c
|
||||
CSRCS += lv_obj_style_gen.c
|
||||
CSRCS += lv_obj_tree.c
|
||||
CSRCS += lv_event.c
|
||||
CSRCS += lv_refr.c
|
||||
CSRCS += lv_theme.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core"
|
||||
534
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_disp.c
Normal file
534
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_disp.c
Normal file
@@ -0,0 +1,534 @@
|
||||
/**
|
||||
* @file lv_disp.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_disp.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../core/lv_refr.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void scr_load_internal(lv_obj_t * scr);
|
||||
static void scr_load_anim_start(lv_anim_t * a);
|
||||
static void opa_scale_anim(void * obj, int32_t v);
|
||||
static void set_x_anim(void * obj, int32_t v);
|
||||
static void set_y_anim(void * obj, int32_t v);
|
||||
static void scr_anim_ready(lv_anim_t * a);
|
||||
static bool is_out_anim(lv_scr_load_anim_t a);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered to get its active screen");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->act_scr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered to get its previous screen");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->prev_scr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a screen active
|
||||
* @param scr pointer to a screen
|
||||
*/
|
||||
void lv_disp_load_scr(lv_obj_t * scr)
|
||||
{
|
||||
lv_scr_load_anim(scr, LV_SCR_LOAD_ANIM_NONE, 0, 0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_layer_top: no display registered to get its top layer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->top_layer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_layer_sys: no display registered to get its sys. layer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->sys_layer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->theme = th;
|
||||
|
||||
if(disp->screen_cnt == 3 &&
|
||||
lv_obj_get_child_cnt(disp->screens[0]) == 0 &&
|
||||
lv_obj_get_child_cnt(disp->screens[1]) == 0 &&
|
||||
lv_obj_get_child_cnt(disp->screens[2]) == 0) {
|
||||
lv_theme_apply(disp->screens[0]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(disp == NULL) disp = lv_disp_get_default();
|
||||
return disp->theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->bg_color = color;
|
||||
|
||||
lv_area_t a;
|
||||
lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
|
||||
_lv_inv_area(disp, &a);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->bg_img = img_src;
|
||||
|
||||
lv_area_t a;
|
||||
lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
|
||||
_lv_inv_area(disp, &a);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->bg_opa = opa;
|
||||
|
||||
lv_area_t a;
|
||||
lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
|
||||
_lv_inv_area(disp, &a);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 * new_scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del)
|
||||
{
|
||||
|
||||
lv_disp_t * d = lv_obj_get_disp(new_scr);
|
||||
lv_obj_t * act_scr = lv_scr_act();
|
||||
|
||||
/*If an other screen load animation is in progress
|
||||
*make target screen loaded immediately. */
|
||||
if(d->scr_to_load && act_scr != d->scr_to_load) {
|
||||
scr_load_internal(d->scr_to_load);
|
||||
lv_anim_del(d->scr_to_load, NULL);
|
||||
lv_obj_set_pos(d->scr_to_load, 0, 0);
|
||||
lv_obj_remove_local_style_prop(d->scr_to_load, LV_STYLE_OPA, 0);
|
||||
|
||||
if(d->del_prev) {
|
||||
lv_obj_del(act_scr);
|
||||
}
|
||||
act_scr = d->scr_to_load;
|
||||
}
|
||||
|
||||
d->scr_to_load = new_scr;
|
||||
|
||||
if(d->prev_scr && d->del_prev) {
|
||||
lv_obj_del(d->prev_scr);
|
||||
d->prev_scr = NULL;
|
||||
}
|
||||
|
||||
d->draw_prev_over_act = is_out_anim(anim_type);
|
||||
d->del_prev = auto_del;
|
||||
|
||||
/*Be sure there is no other animation on the screens*/
|
||||
lv_anim_del(new_scr, NULL);
|
||||
lv_anim_del(lv_scr_act(), NULL);
|
||||
|
||||
/*Be sure both screens are in a normal position*/
|
||||
lv_obj_set_pos(new_scr, 0, 0);
|
||||
lv_obj_set_pos(lv_scr_act(), 0, 0);
|
||||
lv_obj_remove_local_style_prop(new_scr, LV_STYLE_OPA, 0);
|
||||
lv_obj_remove_local_style_prop(lv_scr_act(), LV_STYLE_OPA, 0);
|
||||
|
||||
|
||||
/*Shortcut for immediate load*/
|
||||
if(time == 0 && delay == 0) {
|
||||
scr_load_internal(new_scr);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_anim_t a_new;
|
||||
lv_anim_init(&a_new);
|
||||
lv_anim_set_var(&a_new, new_scr);
|
||||
lv_anim_set_start_cb(&a_new, scr_load_anim_start);
|
||||
lv_anim_set_ready_cb(&a_new, scr_anim_ready);
|
||||
lv_anim_set_time(&a_new, time);
|
||||
lv_anim_set_delay(&a_new, delay);
|
||||
|
||||
lv_anim_t a_old;
|
||||
lv_anim_init(&a_old);
|
||||
lv_anim_set_var(&a_old, d->act_scr);
|
||||
lv_anim_set_time(&a_old, time);
|
||||
lv_anim_set_delay(&a_old, delay);
|
||||
|
||||
switch(anim_type) {
|
||||
case LV_SCR_LOAD_ANIM_NONE:
|
||||
/*Create a dummy animation to apply the delay*/
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, 0, 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OVER_LEFT:
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, lv_disp_get_hor_res(d), 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OVER_RIGHT:
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, -lv_disp_get_hor_res(d), 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OVER_TOP:
|
||||
lv_anim_set_exec_cb(&a_new, set_y_anim);
|
||||
lv_anim_set_values(&a_new, lv_disp_get_ver_res(d), 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OVER_BOTTOM:
|
||||
lv_anim_set_exec_cb(&a_new, set_y_anim);
|
||||
lv_anim_set_values(&a_new, -lv_disp_get_ver_res(d), 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_MOVE_LEFT:
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, lv_disp_get_hor_res(d), 0);
|
||||
|
||||
lv_anim_set_exec_cb(&a_old, set_x_anim);
|
||||
lv_anim_set_values(&a_old, 0, -lv_disp_get_hor_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_MOVE_RIGHT:
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, -lv_disp_get_hor_res(d), 0);
|
||||
|
||||
lv_anim_set_exec_cb(&a_old, set_x_anim);
|
||||
lv_anim_set_values(&a_old, 0, lv_disp_get_hor_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_MOVE_TOP:
|
||||
lv_anim_set_exec_cb(&a_new, set_y_anim);
|
||||
lv_anim_set_values(&a_new, lv_disp_get_ver_res(d), 0);
|
||||
|
||||
lv_anim_set_exec_cb(&a_old, set_y_anim);
|
||||
lv_anim_set_values(&a_old, 0, -lv_disp_get_ver_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_MOVE_BOTTOM:
|
||||
lv_anim_set_exec_cb(&a_new, set_y_anim);
|
||||
lv_anim_set_values(&a_new, -lv_disp_get_ver_res(d), 0);
|
||||
|
||||
lv_anim_set_exec_cb(&a_old, set_y_anim);
|
||||
lv_anim_set_values(&a_old, 0, lv_disp_get_ver_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_FADE_IN:
|
||||
lv_anim_set_exec_cb(&a_new, opa_scale_anim);
|
||||
lv_anim_set_values(&a_new, LV_OPA_TRANSP, LV_OPA_COVER);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_FADE_OUT:
|
||||
lv_anim_set_exec_cb(&a_old, opa_scale_anim);
|
||||
lv_anim_set_values(&a_old, LV_OPA_COVER, LV_OPA_TRANSP);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OUT_LEFT:
|
||||
lv_anim_set_exec_cb(&a_old, set_x_anim);
|
||||
lv_anim_set_values(&a_old, 0, -lv_disp_get_hor_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OUT_RIGHT:
|
||||
lv_anim_set_exec_cb(&a_old, set_x_anim);
|
||||
lv_anim_set_values(&a_old, 0, lv_disp_get_hor_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OUT_TOP:
|
||||
lv_anim_set_exec_cb(&a_old, set_y_anim);
|
||||
lv_anim_set_values(&a_old, 0, -lv_disp_get_ver_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OUT_BOTTOM:
|
||||
lv_anim_set_exec_cb(&a_old, set_y_anim);
|
||||
lv_anim_set_values(&a_old, 0, lv_disp_get_ver_res(d));
|
||||
break;
|
||||
}
|
||||
|
||||
lv_event_send(act_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||
|
||||
lv_anim_start(&a_new);
|
||||
lv_anim_start(&a_old);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(disp) return lv_tick_elaps(disp->last_activity_time);
|
||||
|
||||
lv_disp_t * d;
|
||||
uint32_t t = UINT32_MAX;
|
||||
d = lv_disp_get_next(NULL);
|
||||
while(d) {
|
||||
uint32_t elaps = lv_tick_elaps(d->last_activity_time);
|
||||
t = LV_MIN(t, elaps);
|
||||
d = lv_disp_get_next(d);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_disp_trig_activity: no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->last_activity_time = lv_tick_get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_disp_clean_dcache: no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
if(disp->driver->clean_dcache_cb)
|
||||
disp->driver->clean_dcache_cb(disp->driver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily enable and disable the invalidation of the display.
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @param en true: enable invalidation; false: invalidation
|
||||
*/
|
||||
void lv_disp_enable_invalidation(lv_disp_t * disp, bool en)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->inv_en_cnt += en ? 1 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get display invalidation is enabled.
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @return return true if invalidation is enabled
|
||||
*/
|
||||
bool lv_disp_is_invalidation_enabled(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered");
|
||||
return false;
|
||||
}
|
||||
|
||||
return (disp->inv_en_cnt > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_disp_get_refr_timer: no display registered");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->refr_timer;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void scr_load_internal(lv_obj_t * scr)
|
||||
{
|
||||
lv_disp_t * d = lv_obj_get_disp(scr);
|
||||
if(!d) return; /*Shouldn't happen, just to be sure*/
|
||||
|
||||
lv_obj_t * old_scr = d->act_scr;
|
||||
|
||||
if(d->act_scr) lv_event_send(old_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||
if(d->act_scr) lv_event_send(scr, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||
|
||||
d->act_scr = scr;
|
||||
|
||||
if(d->act_scr) lv_event_send(scr, LV_EVENT_SCREEN_LOADED, NULL);
|
||||
if(d->act_scr) lv_event_send(old_scr, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||
|
||||
lv_obj_invalidate(scr);
|
||||
}
|
||||
|
||||
static void scr_load_anim_start(lv_anim_t * a)
|
||||
{
|
||||
lv_disp_t * d = lv_obj_get_disp(a->var);
|
||||
|
||||
d->prev_scr = lv_scr_act();
|
||||
d->act_scr = a->var;
|
||||
|
||||
lv_event_send(d->act_scr, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||
}
|
||||
|
||||
static void opa_scale_anim(void * obj, int32_t v)
|
||||
{
|
||||
lv_obj_set_style_opa(obj, v, 0);
|
||||
}
|
||||
|
||||
static void set_x_anim(void * obj, int32_t v)
|
||||
{
|
||||
lv_obj_set_x(obj, v);
|
||||
}
|
||||
|
||||
static void set_y_anim(void * obj, int32_t v)
|
||||
{
|
||||
lv_obj_set_y(obj, v);
|
||||
}
|
||||
|
||||
static void scr_anim_ready(lv_anim_t * a)
|
||||
{
|
||||
lv_disp_t * d = lv_obj_get_disp(a->var);
|
||||
|
||||
lv_event_send(d->act_scr, LV_EVENT_SCREEN_LOADED, NULL);
|
||||
lv_event_send(d->prev_scr, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||
|
||||
if(d->prev_scr && d->del_prev) lv_obj_del(d->prev_scr);
|
||||
d->prev_scr = NULL;
|
||||
d->draw_prev_over_act = false;
|
||||
d->scr_to_load = NULL;
|
||||
lv_obj_remove_local_style_prop(a->var, LV_STYLE_OPA, 0);
|
||||
lv_obj_invalidate(d->act_scr);
|
||||
}
|
||||
|
||||
static bool is_out_anim(lv_scr_load_anim_t anim_type)
|
||||
{
|
||||
return anim_type == LV_SCR_LOAD_ANIM_FADE_OUT ||
|
||||
anim_type == LV_SCR_LOAD_ANIM_OUT_LEFT ||
|
||||
anim_type == LV_SCR_LOAD_ANIM_OUT_RIGHT ||
|
||||
anim_type == LV_SCR_LOAD_ANIM_OUT_TOP ||
|
||||
anim_type == LV_SCR_LOAD_ANIM_OUT_BOTTOM;
|
||||
}
|
||||
264
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_disp.h
Normal file
264
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_disp.h
Normal file
@@ -0,0 +1,264 @@
|
||||
/**
|
||||
* @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_IN,
|
||||
LV_SCR_LOAD_ANIM_FADE_ON = LV_SCR_LOAD_ANIM_FADE_IN, /*For backward compatibility*/
|
||||
LV_SCR_LOAD_ANIM_FADE_OUT,
|
||||
LV_SCR_LOAD_ANIM_OUT_LEFT,
|
||||
LV_SCR_LOAD_ANIM_OUT_RIGHT,
|
||||
LV_SCR_LOAD_ANIM_OUT_TOP,
|
||||
LV_SCR_LOAD_ANIM_OUT_BOTTOM,
|
||||
} 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);
|
||||
|
||||
/**
|
||||
* Temporarily enable and disable the invalidation of the display.
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @param en true: enable invalidation; false: invalidation
|
||||
*/
|
||||
void lv_disp_enable_invalidation(lv_disp_t * disp, bool en);
|
||||
|
||||
/**
|
||||
* Get display invalidation is enabled.
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @return return true if invalidation is enabled
|
||||
*/
|
||||
bool lv_disp_is_invalidation_enabled(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*/
|
||||
527
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_event.c
Normal file
527
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_event.c
Normal file
@@ -0,0 +1,527 @@
|
||||
/**
|
||||
* @file lv_event.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "lv_indev.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct _lv_event_dsc_t {
|
||||
lv_event_cb_t cb;
|
||||
void * user_data;
|
||||
lv_event_code_t filter : 8;
|
||||
} lv_event_dsc_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id);
|
||||
static lv_res_t event_send_core(lv_event_t * e);
|
||||
static bool event_is_bubbled(lv_event_t * e);
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_event_t * event_head;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#if LV_LOG_TRACE_EVENT
|
||||
#define EVENT_TRACE(...) LV_LOG_TRACE(__VA_ARGS__)
|
||||
#else
|
||||
#define EVENT_TRACE(...)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_res_t lv_event_send(lv_obj_t * obj, lv_event_code_t event_code, void * param)
|
||||
{
|
||||
if(obj == NULL) return LV_RES_OK;
|
||||
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_event_t e;
|
||||
e.target = obj;
|
||||
e.current_target = obj;
|
||||
e.code = event_code;
|
||||
e.user_data = NULL;
|
||||
e.param = param;
|
||||
e.deleted = 0;
|
||||
e.stop_bubbling = 0;
|
||||
e.stop_processing = 0;
|
||||
|
||||
/*Build a simple linked list from the objects used in the events
|
||||
*It's important to know if this object was deleted by a nested event
|
||||
*called from this `event_cb`.*/
|
||||
e.prev = event_head;
|
||||
event_head = &e;
|
||||
|
||||
/*Send the event*/
|
||||
lv_res_t res = event_send_core(&e);
|
||||
|
||||
/*Remove this element from the list*/
|
||||
event_head = e.prev;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
{
|
||||
const lv_obj_class_t * base;
|
||||
if(class_p == NULL) base = e->current_target->class_p;
|
||||
else base = class_p->base_class;
|
||||
|
||||
/*Find a base in which call the ancestor's event handler_cb if set*/
|
||||
while(base && base->event_cb == NULL) base = base->base_class;
|
||||
|
||||
if(base == NULL) return LV_RES_OK;
|
||||
if(base->event_cb == NULL) return LV_RES_OK;
|
||||
|
||||
/*Call the actual event callback*/
|
||||
e->user_data = NULL;
|
||||
base->event_cb(base, e);
|
||||
|
||||
lv_res_t res = LV_RES_OK;
|
||||
/*Stop if the object is deleted*/
|
||||
if(e->deleted) res = LV_RES_INV;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
lv_obj_t * lv_event_get_target(lv_event_t * e)
|
||||
{
|
||||
return e->target;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_event_get_current_target(lv_event_t * e)
|
||||
{
|
||||
return e->current_target;
|
||||
}
|
||||
|
||||
lv_event_code_t lv_event_get_code(lv_event_t * e)
|
||||
{
|
||||
return e->code & ~LV_EVENT_PREPROCESS;
|
||||
}
|
||||
|
||||
void * lv_event_get_param(lv_event_t * e)
|
||||
{
|
||||
return e->param;
|
||||
}
|
||||
|
||||
void * lv_event_get_user_data(lv_event_t * e)
|
||||
{
|
||||
return e->user_data;
|
||||
}
|
||||
|
||||
void lv_event_stop_bubbling(lv_event_t * e)
|
||||
{
|
||||
e->stop_bubbling = 1;
|
||||
}
|
||||
|
||||
void lv_event_stop_processing(lv_event_t * e)
|
||||
{
|
||||
e->stop_processing = 1;
|
||||
}
|
||||
|
||||
|
||||
uint32_t lv_event_register_id(void)
|
||||
{
|
||||
static uint32_t last_id = _LV_EVENT_LAST;
|
||||
last_id ++;
|
||||
return last_id;
|
||||
}
|
||||
|
||||
void _lv_event_mark_deleted(lv_obj_t * obj)
|
||||
{
|
||||
lv_event_t * e = event_head;
|
||||
|
||||
while(e) {
|
||||
if(e->current_target == obj || e->target == obj) e->deleted = 1;
|
||||
e = e->prev;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct _lv_event_dsc_t * lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter,
|
||||
void * user_data)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
|
||||
obj->spec_attr->event_dsc_cnt++;
|
||||
obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
|
||||
obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
|
||||
|
||||
obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].cb = event_cb;
|
||||
obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].filter = filter;
|
||||
obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].user_data = user_data;
|
||||
|
||||
return &obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1];
|
||||
}
|
||||
|
||||
bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return false;
|
||||
|
||||
int32_t i = 0;
|
||||
for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
|
||||
if(event_cb == NULL || obj->spec_attr->event_dsc[i].cb == event_cb) {
|
||||
/*Shift the remaining event handlers forward*/
|
||||
for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) {
|
||||
obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1];
|
||||
}
|
||||
obj->spec_attr->event_dsc_cnt--;
|
||||
obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
|
||||
obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*No event handler found*/
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj, lv_event_cb_t event_cb, const void * user_data)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return false;
|
||||
|
||||
int32_t i = 0;
|
||||
for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
|
||||
if((event_cb == NULL || obj->spec_attr->event_dsc[i].cb == event_cb) &&
|
||||
obj->spec_attr->event_dsc[i].user_data == user_data) {
|
||||
/*Shift the remaining event handlers forward*/
|
||||
for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) {
|
||||
obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1];
|
||||
}
|
||||
obj->spec_attr->event_dsc_cnt--;
|
||||
obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
|
||||
obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*No event handler found*/
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool lv_obj_remove_event_dsc(lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return false;
|
||||
|
||||
int32_t i = 0;
|
||||
for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
|
||||
if(&obj->spec_attr->event_dsc[i] == event_dsc) {
|
||||
/*Shift the remaining event handlers forward*/
|
||||
for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) {
|
||||
obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1];
|
||||
}
|
||||
obj->spec_attr->event_dsc_cnt--;
|
||||
obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
|
||||
obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*No event handler found*/
|
||||
return false;
|
||||
}
|
||||
|
||||
void * lv_obj_get_event_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return NULL;
|
||||
|
||||
int32_t i = 0;
|
||||
for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
|
||||
if(event_cb == obj->spec_attr->event_dsc[i].cb) return obj->spec_attr->event_dsc[i].user_data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_indev_t * lv_event_get_indev(lv_event_t * e)
|
||||
{
|
||||
|
||||
if(e->code == LV_EVENT_PRESSED ||
|
||||
e->code == LV_EVENT_PRESSING ||
|
||||
e->code == LV_EVENT_PRESS_LOST ||
|
||||
e->code == LV_EVENT_SHORT_CLICKED ||
|
||||
e->code == LV_EVENT_LONG_PRESSED ||
|
||||
e->code == LV_EVENT_LONG_PRESSED_REPEAT ||
|
||||
e->code == LV_EVENT_CLICKED ||
|
||||
e->code == LV_EVENT_RELEASED ||
|
||||
e->code == LV_EVENT_SCROLL_BEGIN ||
|
||||
e->code == LV_EVENT_SCROLL_END ||
|
||||
e->code == LV_EVENT_SCROLL ||
|
||||
e->code == LV_EVENT_GESTURE ||
|
||||
e->code == LV_EVENT_KEY ||
|
||||
e->code == LV_EVENT_FOCUSED ||
|
||||
e->code == LV_EVENT_DEFOCUSED ||
|
||||
e->code == LV_EVENT_LEAVE) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lv_obj_draw_part_dsc_t * lv_event_get_draw_part_dsc(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_DRAW_PART_BEGIN ||
|
||||
e->code == LV_EVENT_DRAW_PART_END) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lv_draw_ctx_t * lv_event_get_draw_ctx(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_DRAW_MAIN ||
|
||||
e->code == LV_EVENT_DRAW_MAIN_BEGIN ||
|
||||
e->code == LV_EVENT_DRAW_MAIN_END ||
|
||||
e->code == LV_EVENT_DRAW_POST ||
|
||||
e->code == LV_EVENT_DRAW_POST_BEGIN ||
|
||||
e->code == LV_EVENT_DRAW_POST_END) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const lv_area_t * lv_event_get_old_size(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_SIZE_CHANGED) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t lv_event_get_key(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_KEY) {
|
||||
uint32_t * k = lv_event_get_param(e);
|
||||
if(k) return *k;
|
||||
else return 0;
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_SCROLL_BEGIN) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_event_set_ext_draw_size(lv_event_t * e, lv_coord_t size)
|
||||
{
|
||||
if(e->code == LV_EVENT_REFR_EXT_DRAW_SIZE) {
|
||||
lv_coord_t * cur_size = lv_event_get_param(e);
|
||||
*cur_size = LV_MAX(*cur_size, size);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
}
|
||||
}
|
||||
|
||||
lv_point_t * lv_event_get_self_size_info(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_GET_SELF_SIZE) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_HIT_TEST) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const lv_area_t * lv_event_get_cover_area(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_COVER_CHECK) {
|
||||
lv_cover_check_info_t * p = lv_event_get_param(e);
|
||||
return p->area;
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res)
|
||||
{
|
||||
if(e->code == LV_EVENT_COVER_CHECK) {
|
||||
lv_cover_check_info_t * p = lv_event_get_param(e);
|
||||
if(res > p->res) p->res = res; /*Save only "stronger" results*/
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(!obj->spec_attr) return NULL;
|
||||
if(id >= obj->spec_attr->event_dsc_cnt) return NULL;
|
||||
|
||||
return &obj->spec_attr->event_dsc[id];
|
||||
}
|
||||
|
||||
static lv_res_t event_send_core(lv_event_t * e)
|
||||
{
|
||||
EVENT_TRACE("Sending event %d to %p with %p param", e->code, (void *)e->current_target, e->param);
|
||||
|
||||
/*Call the input device's feedback callback if set*/
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
if(indev_act) {
|
||||
if(indev_act->driver->feedback_cb) indev_act->driver->feedback_cb(indev_act->driver, e->code);
|
||||
if(e->stop_processing) return LV_RES_OK;
|
||||
if(e->deleted) return LV_RES_INV;
|
||||
}
|
||||
|
||||
lv_res_t res = LV_RES_OK;
|
||||
lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(e->current_target, 0);
|
||||
|
||||
uint32_t i = 0;
|
||||
while(event_dsc && res == LV_RES_OK) {
|
||||
if(event_dsc->cb && ((event_dsc->filter & LV_EVENT_PREPROCESS) == LV_EVENT_PREPROCESS)
|
||||
&& (event_dsc->filter == (LV_EVENT_ALL | LV_EVENT_PREPROCESS) ||
|
||||
(event_dsc->filter & ~LV_EVENT_PREPROCESS) == e->code)) {
|
||||
e->user_data = event_dsc->user_data;
|
||||
event_dsc->cb(e);
|
||||
|
||||
if(e->stop_processing) return LV_RES_OK;
|
||||
/*Stop if the object is deleted*/
|
||||
if(e->deleted) return LV_RES_INV;
|
||||
}
|
||||
|
||||
i++;
|
||||
event_dsc = lv_obj_get_event_dsc(e->current_target, i);
|
||||
}
|
||||
|
||||
res = lv_obj_event_base(NULL, e);
|
||||
|
||||
event_dsc = res == LV_RES_INV ? NULL : lv_obj_get_event_dsc(e->current_target, 0);
|
||||
|
||||
i = 0;
|
||||
while(event_dsc && res == LV_RES_OK) {
|
||||
if(event_dsc->cb && ((event_dsc->filter & LV_EVENT_PREPROCESS) == 0)
|
||||
&& (event_dsc->filter == LV_EVENT_ALL || event_dsc->filter == e->code)) {
|
||||
e->user_data = event_dsc->user_data;
|
||||
event_dsc->cb(e);
|
||||
|
||||
if(e->stop_processing) return LV_RES_OK;
|
||||
/*Stop if the object is deleted*/
|
||||
if(e->deleted) return LV_RES_INV;
|
||||
}
|
||||
|
||||
i++;
|
||||
event_dsc = lv_obj_get_event_dsc(e->current_target, i);
|
||||
}
|
||||
|
||||
if(res == LV_RES_OK && e->current_target->parent && event_is_bubbled(e)) {
|
||||
e->current_target = e->current_target->parent;
|
||||
res = event_send_core(e);
|
||||
if(res != LV_RES_OK) return LV_RES_INV;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool event_is_bubbled(lv_event_t * e)
|
||||
{
|
||||
if(e->stop_bubbling) return false;
|
||||
|
||||
/*Event codes that always bubble*/
|
||||
switch(e->code) {
|
||||
case LV_EVENT_CHILD_CREATED:
|
||||
case LV_EVENT_CHILD_DELETED:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*Check other codes only if bubbling is enabled*/
|
||||
if(lv_obj_has_flag(e->current_target, LV_OBJ_FLAG_EVENT_BUBBLE) == false) return false;
|
||||
|
||||
switch(e->code) {
|
||||
case LV_EVENT_HIT_TEST:
|
||||
case LV_EVENT_COVER_CHECK:
|
||||
case LV_EVENT_REFR_EXT_DRAW_SIZE:
|
||||
case LV_EVENT_DRAW_MAIN_BEGIN:
|
||||
case LV_EVENT_DRAW_MAIN:
|
||||
case LV_EVENT_DRAW_MAIN_END:
|
||||
case LV_EVENT_DRAW_POST_BEGIN:
|
||||
case LV_EVENT_DRAW_POST:
|
||||
case LV_EVENT_DRAW_POST_END:
|
||||
case LV_EVENT_DRAW_PART_BEGIN:
|
||||
case LV_EVENT_DRAW_PART_END:
|
||||
case LV_EVENT_REFRESH:
|
||||
case LV_EVENT_DELETE:
|
||||
case LV_EVENT_CHILD_CREATED:
|
||||
case LV_EVENT_CHILD_DELETED:
|
||||
case LV_EVENT_CHILD_CHANGED:
|
||||
case LV_EVENT_SIZE_CHANGED:
|
||||
case LV_EVENT_STYLE_CHANGED:
|
||||
case LV_EVENT_GET_SELF_SIZE:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
363
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_event.h
Normal file
363
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_event.h
Normal file
@@ -0,0 +1,363 @@
|
||||
/**
|
||||
* @file lv_event.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_EVENT_H
|
||||
#define LV_EVENT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
|
||||
/*********************
|
||||
* 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. The event parameter is a pointer to the animation of the scroll. Can be modified*/
|
||||
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*/
|
||||
497
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_group.c
Normal file
497
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_group.c
Normal file
@@ -0,0 +1,497 @@
|
||||
/**
|
||||
* @file lv_group.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
|
||||
#include "lv_group.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
#include "../core/lv_obj.h"
|
||||
#include "../core/lv_indev.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *),
|
||||
void * (*move)(const lv_ll_t *, const void *));
|
||||
static void lv_group_refocus(lv_group_t * g);
|
||||
static lv_indev_t * get_indev(const lv_group_t * g);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_group_t * default_group;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void _lv_group_init(void)
|
||||
{
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_group_ll), sizeof(lv_group_t));
|
||||
}
|
||||
|
||||
lv_group_t * lv_group_create(void)
|
||||
{
|
||||
lv_group_t * group = _lv_ll_ins_head(&LV_GC_ROOT(_lv_group_ll));
|
||||
LV_ASSERT_MALLOC(group);
|
||||
if(group == NULL) return NULL;
|
||||
_lv_ll_init(&group->obj_ll, sizeof(lv_obj_t *));
|
||||
|
||||
group->obj_focus = NULL;
|
||||
group->frozen = 0;
|
||||
group->focus_cb = NULL;
|
||||
group->edge_cb = NULL;
|
||||
group->editing = 0;
|
||||
group->refocus_policy = LV_GROUP_REFOCUS_POLICY_PREV;
|
||||
group->wrap = 1;
|
||||
|
||||
#if LV_USE_USER_DATA
|
||||
group->user_data = NULL;
|
||||
#endif
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
void lv_group_del(lv_group_t * group)
|
||||
{
|
||||
/*Defocus the currently focused object*/
|
||||
if(group->obj_focus != NULL) {
|
||||
lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
}
|
||||
|
||||
/*Remove the objects from the group*/
|
||||
lv_obj_t ** obj;
|
||||
_LV_LL_READ(&group->obj_ll, obj) {
|
||||
if((*obj)->spec_attr)(*obj)->spec_attr->group_p = NULL;
|
||||
}
|
||||
|
||||
/*Remove the group from any indev devices */
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
while(indev) {
|
||||
if(indev->group == group) {
|
||||
lv_indev_set_group(indev, NULL);
|
||||
}
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
_lv_ll_clear(&(group->obj_ll));
|
||||
_lv_ll_remove(&LV_GC_ROOT(_lv_group_ll), group);
|
||||
lv_mem_free(group);
|
||||
}
|
||||
|
||||
void lv_group_set_default(lv_group_t * group)
|
||||
{
|
||||
default_group = group;
|
||||
}
|
||||
|
||||
lv_group_t * lv_group_get_default(void)
|
||||
{
|
||||
return default_group;
|
||||
}
|
||||
|
||||
void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj)
|
||||
{
|
||||
if(group == NULL) return;
|
||||
|
||||
LV_LOG_TRACE("begin");
|
||||
|
||||
/*Be sure the object is removed from its current group*/
|
||||
lv_group_remove_obj(obj);
|
||||
|
||||
/*Do not add the object twice*/
|
||||
lv_obj_t ** obj_i;
|
||||
_LV_LL_READ(&group->obj_ll, obj_i) {
|
||||
if((*obj_i) == obj) {
|
||||
LV_LOG_INFO("the object is already added to this group");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*If the object is already in a group and focused then refocus it*/
|
||||
lv_group_t * group_cur = lv_obj_get_group(obj);
|
||||
if(group_cur) {
|
||||
if(obj->spec_attr->group_p && *(obj->spec_attr->group_p->obj_focus) == obj) {
|
||||
lv_group_refocus(group_cur);
|
||||
|
||||
LV_LOG_INFO("changing object's group");
|
||||
}
|
||||
}
|
||||
|
||||
if(obj->spec_attr == NULL) lv_obj_allocate_spec_attr(obj);
|
||||
obj->spec_attr->group_p = group;
|
||||
|
||||
lv_obj_t ** next = _lv_ll_ins_tail(&group->obj_ll);
|
||||
LV_ASSERT_MALLOC(next);
|
||||
if(next == NULL) return;
|
||||
*next = obj;
|
||||
|
||||
/*If the head and the tail is equal then there is only one object in the linked list.
|
||||
*In this case automatically activate it*/
|
||||
if(_lv_ll_get_head(&group->obj_ll) == next) {
|
||||
lv_group_refocus(group);
|
||||
}
|
||||
|
||||
LV_LOG_TRACE("finished");
|
||||
}
|
||||
|
||||
void lv_group_swap_obj(lv_obj_t * obj1, lv_obj_t * obj2)
|
||||
{
|
||||
lv_group_t * g1 = lv_obj_get_group(obj1);
|
||||
lv_group_t * g2 = lv_obj_get_group(obj2);
|
||||
if(g1 != g2) return;
|
||||
if(g1 == NULL) return;
|
||||
|
||||
/*Do not add the object twice*/
|
||||
lv_obj_t ** obj_i;
|
||||
_LV_LL_READ(&g1->obj_ll, obj_i) {
|
||||
if((*obj_i) == obj1)(*obj_i) = obj2;
|
||||
else if((*obj_i) == obj2)(*obj_i) = obj1;
|
||||
}
|
||||
|
||||
if(*g1->obj_focus == obj1) lv_group_focus_obj(obj2);
|
||||
else if(*g1->obj_focus == obj2) lv_group_focus_obj(obj1);
|
||||
|
||||
}
|
||||
|
||||
void lv_group_remove_obj(lv_obj_t * obj)
|
||||
{
|
||||
lv_group_t * g = lv_obj_get_group(obj);
|
||||
if(g == NULL) return;
|
||||
|
||||
LV_LOG_TRACE("begin");
|
||||
|
||||
/*Focus on the next object*/
|
||||
if(g->obj_focus && *g->obj_focus == obj) {
|
||||
if(g->frozen) g->frozen = 0;
|
||||
|
||||
/*If this is the only object in the group then focus to nothing.*/
|
||||
if(_lv_ll_get_head(&g->obj_ll) == g->obj_focus && _lv_ll_get_tail(&g->obj_ll) == g->obj_focus) {
|
||||
lv_event_send(*g->obj_focus, LV_EVENT_DEFOCUSED, get_indev(g));
|
||||
}
|
||||
/*If there more objects in the group then focus to the next/prev object*/
|
||||
else {
|
||||
lv_group_refocus(g);
|
||||
}
|
||||
}
|
||||
|
||||
/*If the focuses object is still the same then it was the only object in the group but it will
|
||||
*be deleted. Set the `obj_focus` to NULL to get back to the initial state of the group with
|
||||
*zero objects*/
|
||||
if(g->obj_focus && *g->obj_focus == obj) {
|
||||
g->obj_focus = NULL;
|
||||
}
|
||||
|
||||
/*Search the object and remove it from its group*/
|
||||
lv_obj_t ** i;
|
||||
_LV_LL_READ(&g->obj_ll, i) {
|
||||
if(*i == obj) {
|
||||
_lv_ll_remove(&g->obj_ll, i);
|
||||
lv_mem_free(i);
|
||||
if(obj->spec_attr) obj->spec_attr->group_p = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LV_LOG_TRACE("finished");
|
||||
}
|
||||
|
||||
void lv_group_remove_all_objs(lv_group_t * group)
|
||||
{
|
||||
/*Defocus the currently focused object*/
|
||||
if(group->obj_focus != NULL) {
|
||||
lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
group->obj_focus = NULL;
|
||||
}
|
||||
|
||||
/*Remove the objects from the group*/
|
||||
lv_obj_t ** obj;
|
||||
_LV_LL_READ(&group->obj_ll, obj) {
|
||||
if((*obj)->spec_attr)(*obj)->spec_attr->group_p = NULL;
|
||||
}
|
||||
|
||||
_lv_ll_clear(&(group->obj_ll));
|
||||
}
|
||||
|
||||
void lv_group_focus_obj(lv_obj_t * obj)
|
||||
{
|
||||
if(obj == NULL) return;
|
||||
lv_group_t * g = lv_obj_get_group(obj);
|
||||
if(g == NULL) return;
|
||||
|
||||
if(g->frozen != 0) return;
|
||||
|
||||
/*On defocus edit mode must be leaved*/
|
||||
lv_group_set_editing(g, false);
|
||||
|
||||
lv_obj_t ** i;
|
||||
_LV_LL_READ(&g->obj_ll, i) {
|
||||
if(*i == obj) {
|
||||
if(g->obj_focus != NULL && obj != *g->obj_focus) { /*Do not defocus if the same object needs to be focused again*/
|
||||
lv_res_t res = lv_event_send(*g->obj_focus, LV_EVENT_DEFOCUSED, get_indev(g));
|
||||
if(res != LV_RES_OK) return;
|
||||
lv_obj_invalidate(*g->obj_focus);
|
||||
}
|
||||
|
||||
g->obj_focus = i;
|
||||
|
||||
if(g->obj_focus != NULL) {
|
||||
if(g->focus_cb) g->focus_cb(g);
|
||||
lv_res_t res = lv_event_send(*g->obj_focus, LV_EVENT_FOCUSED, get_indev(g));
|
||||
if(res != LV_RES_OK) return;
|
||||
lv_obj_invalidate(*g->obj_focus);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_group_focus_next(lv_group_t * group)
|
||||
{
|
||||
bool focus_changed = focus_next_core(group, _lv_ll_get_head, _lv_ll_get_next);
|
||||
if(group->edge_cb) {
|
||||
if(!focus_changed)
|
||||
group->edge_cb(group, true);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_group_focus_prev(lv_group_t * group)
|
||||
{
|
||||
bool focus_changed = focus_next_core(group, _lv_ll_get_tail, _lv_ll_get_prev);
|
||||
if(group->edge_cb) {
|
||||
if(!focus_changed)
|
||||
group->edge_cb(group, false);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_group_focus_freeze(lv_group_t * group, bool en)
|
||||
{
|
||||
if(en == false) group->frozen = 0;
|
||||
else group->frozen = 1;
|
||||
}
|
||||
|
||||
lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c)
|
||||
{
|
||||
lv_obj_t * act = lv_group_get_focused(group);
|
||||
if(act == NULL) return LV_RES_OK;
|
||||
|
||||
if(lv_obj_has_state(act, LV_STATE_DISABLED)) return LV_RES_OK;
|
||||
|
||||
return lv_event_send(act, LV_EVENT_KEY, &c);
|
||||
}
|
||||
|
||||
void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb)
|
||||
{
|
||||
group->focus_cb = focus_cb;
|
||||
}
|
||||
|
||||
void lv_group_set_edge_cb(lv_group_t * group, lv_group_edge_cb_t edge_cb)
|
||||
{
|
||||
group->edge_cb = edge_cb;
|
||||
}
|
||||
|
||||
void lv_group_set_editing(lv_group_t * group, bool edit)
|
||||
{
|
||||
if(group == NULL) return;
|
||||
uint8_t en_val = edit ? 1 : 0;
|
||||
|
||||
if(en_val == group->editing) return; /*Do not set the same mode again*/
|
||||
|
||||
group->editing = en_val;
|
||||
lv_obj_t * focused = lv_group_get_focused(group);
|
||||
|
||||
if(focused) {
|
||||
lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group));
|
||||
if(res != LV_RES_OK) return;
|
||||
|
||||
lv_obj_invalidate(focused);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_group_set_refocus_policy(lv_group_t * group, lv_group_refocus_policy_t policy)
|
||||
{
|
||||
group->refocus_policy = policy & 0x01;
|
||||
}
|
||||
|
||||
void lv_group_set_wrap(lv_group_t * group, bool en)
|
||||
{
|
||||
group->wrap = en ? 1 : 0;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_group_get_focused(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return NULL;
|
||||
if(group->obj_focus == NULL) return NULL;
|
||||
|
||||
return *group->obj_focus;
|
||||
}
|
||||
|
||||
lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return NULL;
|
||||
return group->focus_cb;
|
||||
}
|
||||
|
||||
lv_group_edge_cb_t lv_group_get_edge_cb(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return NULL;
|
||||
return group->edge_cb;
|
||||
}
|
||||
|
||||
bool lv_group_get_editing(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return false;
|
||||
return group->editing ? true : false;
|
||||
}
|
||||
|
||||
bool lv_group_get_wrap(lv_group_t * group)
|
||||
{
|
||||
if(!group) return false;
|
||||
return group->wrap ? true : false;
|
||||
}
|
||||
|
||||
uint32_t lv_group_get_obj_count(lv_group_t * group)
|
||||
{
|
||||
return _lv_ll_get_len(&group->obj_ll);
|
||||
}
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_group_refocus(lv_group_t * g)
|
||||
{
|
||||
/*Refocus must temporarily allow wrapping to work correctly*/
|
||||
uint8_t temp_wrap = g->wrap;
|
||||
g->wrap = 1;
|
||||
|
||||
if(g->refocus_policy == LV_GROUP_REFOCUS_POLICY_NEXT)
|
||||
lv_group_focus_next(g);
|
||||
else if(g->refocus_policy == LV_GROUP_REFOCUS_POLICY_PREV)
|
||||
lv_group_focus_prev(g);
|
||||
/*Restore wrap property*/
|
||||
g->wrap = temp_wrap;
|
||||
}
|
||||
|
||||
static bool focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *),
|
||||
void * (*move)(const lv_ll_t *, const void *))
|
||||
{
|
||||
bool focus_changed = false;
|
||||
if(group->frozen) return focus_changed;
|
||||
|
||||
lv_obj_t ** obj_next = group->obj_focus;
|
||||
lv_obj_t ** obj_sentinel = NULL;
|
||||
bool can_move = true;
|
||||
bool can_begin = true;
|
||||
|
||||
for(;;) {
|
||||
if(obj_next == NULL) {
|
||||
if(group->wrap || obj_sentinel == NULL) {
|
||||
if(!can_begin) return focus_changed;
|
||||
obj_next = begin(&group->obj_ll);
|
||||
can_move = false;
|
||||
can_begin = false;
|
||||
}
|
||||
else {
|
||||
/*Currently focused object is the last/first in the group, keep it that way*/
|
||||
return focus_changed;
|
||||
}
|
||||
}
|
||||
|
||||
if(obj_sentinel == NULL) {
|
||||
obj_sentinel = obj_next;
|
||||
if(obj_sentinel == NULL) return focus_changed; /*Group is empty*/
|
||||
}
|
||||
|
||||
if(can_move) {
|
||||
obj_next = move(&group->obj_ll, obj_next);
|
||||
|
||||
/*Give up if we walked the entire list and haven't found another visible object*/
|
||||
if(obj_next == obj_sentinel) return focus_changed;
|
||||
}
|
||||
|
||||
can_move = true;
|
||||
|
||||
if(obj_next == NULL) continue;
|
||||
if(lv_obj_get_state(*obj_next) & LV_STATE_DISABLED) continue;
|
||||
|
||||
/*Hidden objects don't receive focus.
|
||||
*If any parent is hidden, the object is also hidden)*/
|
||||
lv_obj_t * parent = *obj_next;
|
||||
while(parent) {
|
||||
if(lv_obj_has_flag(parent, LV_OBJ_FLAG_HIDDEN)) break;
|
||||
parent = lv_obj_get_parent(parent);
|
||||
}
|
||||
|
||||
if(parent && lv_obj_has_flag(parent, LV_OBJ_FLAG_HIDDEN)) continue;
|
||||
|
||||
/*If we got her a good candidate is found*/
|
||||
break;
|
||||
}
|
||||
|
||||
if(obj_next == group->obj_focus) return focus_changed; /*There's only one visible object and it's already focused*/
|
||||
|
||||
if(group->obj_focus) {
|
||||
lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
|
||||
if(res != LV_RES_OK) return focus_changed;
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
}
|
||||
|
||||
group->obj_focus = obj_next;
|
||||
|
||||
lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group));
|
||||
if(res != LV_RES_OK) return focus_changed;
|
||||
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
|
||||
if(group->focus_cb) group->focus_cb(group);
|
||||
focus_changed = true;
|
||||
return focus_changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an indev preferably with KEYPAD or ENCOEDR type that uses the given group.
|
||||
* In other words, find an indev, that is related to the given group.
|
||||
* In the worst case simply return the latest indev
|
||||
* @param g a group the find in the indevs
|
||||
* @return the suggested indev
|
||||
*/
|
||||
static lv_indev_t * get_indev(const lv_group_t * g)
|
||||
{
|
||||
lv_indev_t * indev_encoder = NULL;
|
||||
lv_indev_t * indev_group = NULL;
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
while(indev) {
|
||||
lv_indev_type_t indev_type = lv_indev_get_type(indev);
|
||||
if(indev->group == g) {
|
||||
/*Prefer KEYPAD*/
|
||||
if(indev_type == LV_INDEV_TYPE_KEYPAD) return indev;
|
||||
if(indev_type == LV_INDEV_TYPE_ENCODER) indev_encoder = indev;
|
||||
indev_group = indev;
|
||||
}
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
if(indev_encoder) return indev_encoder;
|
||||
if(indev_group) return indev_group;
|
||||
|
||||
/*In lack of a better option use the first input device. (It can be NULL if there is no input device)*/
|
||||
return lv_indev_get_next(NULL);
|
||||
}
|
||||
|
||||
266
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_group.h
Normal file
266
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_group.h
Normal file
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* @file lv_group.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GROUP_H
|
||||
#define LV_GROUP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#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 *);
|
||||
typedef void (*lv_group_edge_cb_t)(struct _lv_group_t *, bool);
|
||||
|
||||
/**
|
||||
* 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)*/
|
||||
lv_group_edge_cb_t edge_cb; /**< A function to call when an edge is reached, no more focus
|
||||
targets are available in this direction (to allow edge feedback
|
||||
like a sound or a scroll bounce) */
|
||||
|
||||
#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 a function for a group which will be called when a focus edge is reached
|
||||
* @param group pointer to a group
|
||||
* @param edge_cb the call back function or NULL if unused
|
||||
*/
|
||||
void lv_group_set_edge_cb(lv_group_t * group, lv_group_edge_cb_t edge_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 edge callback function of a group
|
||||
* @param group pointer to a group
|
||||
* @return the call back function or NULL if not set
|
||||
*/
|
||||
lv_group_edge_cb_t lv_group_get_edge_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*/
|
||||
1161
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_indev.c
Normal file
1161
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_indev.c
Normal file
File diff suppressed because it is too large
Load Diff
176
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_indev.h
Normal file
176
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_indev.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* Enable or disable one or all input devices (default enabled)
|
||||
* @param indev pointer to an input device or NULL to enable/disable all of them
|
||||
* @param en true to enable, false to disable
|
||||
*/
|
||||
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*/
|
||||
@@ -0,0 +1,652 @@
|
||||
/**
|
||||
* @file lv_indev_scroll.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_indev.h"
|
||||
#include "lv_indev_scroll.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define ELASTIC_SLOWNESS_FACTOR 4 /*Scrolling on elastic parts are slower by this factor*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc);
|
||||
static void init_scroll_limits(_lv_indev_proc_t * proc);
|
||||
static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs);
|
||||
static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs);
|
||||
static void scroll_limit_diff(_lv_indev_proc_t * proc, lv_coord_t * diff_x, lv_coord_t * diff_y);
|
||||
static lv_coord_t scroll_throw_predict_y(_lv_indev_proc_t * proc);
|
||||
static lv_coord_t scroll_throw_predict_x(_lv_indev_proc_t * proc);
|
||||
static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_t scroll_start, lv_coord_t scroll_end,
|
||||
lv_dir_t dir);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void _lv_indev_scroll_handler(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj;
|
||||
/*If there is no scroll object yet try to find one*/
|
||||
if(scroll_obj == NULL) {
|
||||
proc->types.pointer.scroll_sum.x += proc->types.pointer.vect.x;
|
||||
proc->types.pointer.scroll_sum.y += proc->types.pointer.vect.y;
|
||||
|
||||
scroll_obj = find_scroll_obj(proc);
|
||||
if(scroll_obj == NULL) return;
|
||||
|
||||
init_scroll_limits(proc);
|
||||
|
||||
lv_event_send(scroll_obj, LV_EVENT_SCROLL_BEGIN, NULL);
|
||||
if(proc->reset_query) return;
|
||||
}
|
||||
|
||||
/*Set new position or scroll if the vector is not zero*/
|
||||
if(proc->types.pointer.vect.x != 0 || proc->types.pointer.vect.y != 0) {
|
||||
lv_coord_t diff_x = 0;
|
||||
lv_coord_t diff_y = 0;
|
||||
|
||||
if(proc->types.pointer.scroll_dir == LV_DIR_HOR) {
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj);
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj);
|
||||
diff_x = elastic_diff(scroll_obj, proc->types.pointer.vect.x, sl, sr, LV_DIR_HOR);
|
||||
}
|
||||
else {
|
||||
lv_coord_t st = lv_obj_get_scroll_top(scroll_obj);
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj);
|
||||
diff_y = elastic_diff(scroll_obj, proc->types.pointer.vect.y, st, sb, LV_DIR_VER);
|
||||
}
|
||||
|
||||
lv_dir_t scroll_dir = lv_obj_get_scroll_dir(scroll_obj);
|
||||
if((scroll_dir & LV_DIR_LEFT) == 0 && diff_x > 0) diff_x = 0;
|
||||
if((scroll_dir & LV_DIR_RIGHT) == 0 && diff_x < 0) diff_x = 0;
|
||||
if((scroll_dir & LV_DIR_TOP) == 0 && diff_y > 0) diff_y = 0;
|
||||
if((scroll_dir & LV_DIR_BOTTOM) == 0 && diff_y < 0) diff_y = 0;
|
||||
|
||||
/*Respect the scroll limit area*/
|
||||
scroll_limit_diff(proc, &diff_x, &diff_y);
|
||||
|
||||
_lv_obj_scroll_by_raw(scroll_obj, diff_x, diff_y);
|
||||
if(proc->reset_query) return;
|
||||
proc->types.pointer.scroll_sum.x += diff_x;
|
||||
proc->types.pointer.scroll_sum.y += diff_y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _lv_indev_scroll_throw_handler(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj;
|
||||
if(scroll_obj == NULL) return;
|
||||
if(proc->types.pointer.scroll_dir == LV_DIR_NONE) return;
|
||||
|
||||
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
lv_coord_t scroll_throw = indev_act->driver->scroll_throw;
|
||||
|
||||
if(lv_obj_has_flag(scroll_obj, LV_OBJ_FLAG_SCROLL_MOMENTUM) == false) {
|
||||
proc->types.pointer.scroll_throw_vect.y = 0;
|
||||
proc->types.pointer.scroll_throw_vect.x = 0;
|
||||
}
|
||||
|
||||
lv_scroll_snap_t align_x = lv_obj_get_scroll_snap_x(scroll_obj);
|
||||
lv_scroll_snap_t align_y = lv_obj_get_scroll_snap_y(scroll_obj);
|
||||
|
||||
if(proc->types.pointer.scroll_dir == LV_DIR_VER) {
|
||||
proc->types.pointer.scroll_throw_vect.x = 0;
|
||||
/*If no snapping "throw"*/
|
||||
if(align_y == LV_SCROLL_SNAP_NONE) {
|
||||
proc->types.pointer.scroll_throw_vect.y =
|
||||
proc->types.pointer.scroll_throw_vect.y * (100 - scroll_throw) / 100;
|
||||
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj);
|
||||
lv_coord_t st = lv_obj_get_scroll_top(scroll_obj);
|
||||
|
||||
proc->types.pointer.scroll_throw_vect.y = elastic_diff(scroll_obj, proc->types.pointer.scroll_throw_vect.y, st, sb,
|
||||
LV_DIR_VER);
|
||||
|
||||
lv_obj_scroll_by(scroll_obj, 0, proc->types.pointer.scroll_throw_vect.y, LV_ANIM_OFF);
|
||||
}
|
||||
/*With snapping find the nearest snap point and scroll there*/
|
||||
else {
|
||||
lv_coord_t diff_y = scroll_throw_predict_y(proc);
|
||||
proc->types.pointer.scroll_throw_vect.y = 0;
|
||||
scroll_limit_diff(proc, NULL, &diff_y);
|
||||
lv_coord_t y = find_snap_point_y(scroll_obj, LV_COORD_MIN, LV_COORD_MAX, diff_y);
|
||||
lv_obj_scroll_by(scroll_obj, 0, diff_y + y, LV_ANIM_ON);
|
||||
}
|
||||
}
|
||||
else if(proc->types.pointer.scroll_dir == LV_DIR_HOR) {
|
||||
proc->types.pointer.scroll_throw_vect.y = 0;
|
||||
/*If no snapping "throw"*/
|
||||
if(align_x == LV_SCROLL_SNAP_NONE) {
|
||||
proc->types.pointer.scroll_throw_vect.x =
|
||||
proc->types.pointer.scroll_throw_vect.x * (100 - scroll_throw) / 100;
|
||||
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj);
|
||||
|
||||
proc->types.pointer.scroll_throw_vect.x = elastic_diff(scroll_obj, proc->types.pointer.scroll_throw_vect.x, sl, sr,
|
||||
LV_DIR_HOR);
|
||||
|
||||
lv_obj_scroll_by(scroll_obj, proc->types.pointer.scroll_throw_vect.x, 0, LV_ANIM_OFF);
|
||||
}
|
||||
/*With snapping find the nearest snap point and scroll there*/
|
||||
else {
|
||||
lv_coord_t diff_x = scroll_throw_predict_x(proc);
|
||||
proc->types.pointer.scroll_throw_vect.x = 0;
|
||||
scroll_limit_diff(proc, &diff_x, NULL);
|
||||
lv_coord_t x = find_snap_point_x(scroll_obj, LV_COORD_MIN, LV_COORD_MAX, diff_x);
|
||||
lv_obj_scroll_by(scroll_obj, x + diff_x, 0, LV_ANIM_ON);
|
||||
}
|
||||
}
|
||||
|
||||
/*Check if the scroll has finished*/
|
||||
if(proc->types.pointer.scroll_throw_vect.x == 0 && proc->types.pointer.scroll_throw_vect.y == 0) {
|
||||
/*Revert if scrolled in*/
|
||||
/*If vertically scrollable and not controlled by snap*/
|
||||
if(align_y == LV_SCROLL_SNAP_NONE) {
|
||||
lv_coord_t st = lv_obj_get_scroll_top(scroll_obj);
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj);
|
||||
if(st > 0 || sb > 0) {
|
||||
if(st < 0) {
|
||||
lv_obj_scroll_by(scroll_obj, 0, st, LV_ANIM_ON);
|
||||
}
|
||||
else if(sb < 0) {
|
||||
lv_obj_scroll_by(scroll_obj, 0, -sb, LV_ANIM_ON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*If horizontally scrollable and not controlled by snap*/
|
||||
if(align_x == LV_SCROLL_SNAP_NONE) {
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj);
|
||||
if(sl > 0 || sr > 0) {
|
||||
if(sl < 0) {
|
||||
lv_obj_scroll_by(scroll_obj, sl, 0, LV_ANIM_ON);
|
||||
}
|
||||
else if(sr < 0) {
|
||||
lv_obj_scroll_by(scroll_obj, -sr, 0, LV_ANIM_ON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lv_event_send(scroll_obj, LV_EVENT_SCROLL_END, indev_act);
|
||||
if(proc->reset_query) return;
|
||||
|
||||
proc->types.pointer.scroll_dir = LV_DIR_NONE;
|
||||
proc->types.pointer.scroll_obj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(indev == NULL) return 0;
|
||||
lv_coord_t v;
|
||||
switch(dir) {
|
||||
case LV_DIR_VER:
|
||||
v = indev->proc.types.pointer.scroll_throw_vect_ori.y;
|
||||
break;
|
||||
case LV_DIR_HOR:
|
||||
v = indev->proc.types.pointer.scroll_throw_vect_ori.x;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv_coord_t scroll_throw = indev->driver->scroll_throw;
|
||||
lv_coord_t sum = 0;
|
||||
while(v) {
|
||||
sum += v;
|
||||
v = v * (100 - scroll_throw) / 100;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
void lv_indev_scroll_get_snap_dist(lv_obj_t * obj, lv_point_t * p)
|
||||
{
|
||||
p->x = find_snap_point_x(obj, obj->coords.x1, obj->coords.x2, 0);
|
||||
p->y = find_snap_point_y(obj, obj->coords.y1, obj->coords.y2, 0);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_obj_t * obj_candidate = NULL;
|
||||
lv_dir_t dir_candidate = LV_DIR_NONE;
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
lv_coord_t scroll_limit = indev_act->driver->scroll_limit;
|
||||
|
||||
/*Go until find a scrollable object in the current direction
|
||||
*More precisely:
|
||||
* 1. Check the pressed object and all of its ancestors and try to find an object which is scrollable
|
||||
* 2. Scrollable means it has some content out of its area
|
||||
* 3. If an object can be scrolled into the current direction then use it ("real match"")
|
||||
* 4. If can be scrolled on the current axis (hor/ver) save it as candidate (at least show an elastic scroll effect)
|
||||
* 5. Use the last candidate. Always the "deepest" parent or the object from point 3*/
|
||||
lv_obj_t * obj_act = proc->types.pointer.act_obj;
|
||||
|
||||
/*Decide if it's a horizontal or vertical scroll*/
|
||||
bool hor_en = false;
|
||||
bool ver_en = false;
|
||||
if(LV_ABS(proc->types.pointer.scroll_sum.x) > LV_ABS(proc->types.pointer.scroll_sum.y)) {
|
||||
hor_en = true;
|
||||
}
|
||||
else {
|
||||
ver_en = true;
|
||||
}
|
||||
|
||||
while(obj_act) {
|
||||
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLLABLE) == false) {
|
||||
/*If this object don't want to chain the scroll to the parent stop searching*/
|
||||
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLL_CHAIN_HOR) == false && hor_en) break;
|
||||
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLL_CHAIN_VER) == false && ver_en) break;
|
||||
|
||||
obj_act = lv_obj_get_parent(obj_act);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*Consider both up-down or left/right scrollable according to the current direction*/
|
||||
bool up_en = ver_en;
|
||||
bool down_en = ver_en;
|
||||
bool left_en = hor_en;
|
||||
bool right_en = hor_en;
|
||||
|
||||
/*The object might have disabled some directions.*/
|
||||
lv_dir_t scroll_dir = lv_obj_get_scroll_dir(obj_act);
|
||||
if((scroll_dir & LV_DIR_LEFT) == 0) left_en = false;
|
||||
if((scroll_dir & LV_DIR_RIGHT) == 0) right_en = false;
|
||||
if((scroll_dir & LV_DIR_TOP) == 0) up_en = false;
|
||||
if((scroll_dir & LV_DIR_BOTTOM) == 0) down_en = false;
|
||||
|
||||
/*The object is scrollable to a direction if its content overflow in that direction.*/
|
||||
lv_coord_t st = lv_obj_get_scroll_top(obj_act);
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(obj_act);
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(obj_act);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(obj_act);
|
||||
|
||||
/*If this object is scrollable into the current scroll direction then save it as a candidate.
|
||||
*It's important only to be scrollable on the current axis (hor/ver) because if the scroll
|
||||
*is propagated to this object it can show at least elastic scroll effect.
|
||||
*But if not hor/ver scrollable do not scroll it at all (so it's not a good candidate)*/
|
||||
if((st > 0 || sb > 0) &&
|
||||
((up_en && proc->types.pointer.scroll_sum.y >= scroll_limit) ||
|
||||
(down_en && proc->types.pointer.scroll_sum.y <= - scroll_limit))) {
|
||||
obj_candidate = obj_act;
|
||||
dir_candidate = LV_DIR_VER;
|
||||
}
|
||||
|
||||
if((sl > 0 || sr > 0) &&
|
||||
((left_en && proc->types.pointer.scroll_sum.x >= scroll_limit) ||
|
||||
(right_en && proc->types.pointer.scroll_sum.x <= - scroll_limit))) {
|
||||
obj_candidate = obj_act;
|
||||
dir_candidate = LV_DIR_HOR;
|
||||
}
|
||||
|
||||
if(st <= 0) up_en = false;
|
||||
if(sb <= 0) down_en = false;
|
||||
if(sl <= 0) left_en = false;
|
||||
if(sr <= 0) right_en = false;
|
||||
|
||||
/*If the object really can be scrolled into the current direction the use it.*/
|
||||
if((left_en && proc->types.pointer.scroll_sum.x >= scroll_limit) ||
|
||||
(right_en && proc->types.pointer.scroll_sum.x <= - scroll_limit) ||
|
||||
(up_en && proc->types.pointer.scroll_sum.y >= scroll_limit) ||
|
||||
(down_en && proc->types.pointer.scroll_sum.y <= - scroll_limit)) {
|
||||
proc->types.pointer.scroll_dir = hor_en ? LV_DIR_HOR : LV_DIR_VER;
|
||||
break;
|
||||
}
|
||||
|
||||
/*If this object don't want to chain the scroll to the parent stop searching*/
|
||||
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLL_CHAIN_HOR) == false && hor_en) break;
|
||||
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLL_CHAIN_VER) == false && ver_en) break;
|
||||
|
||||
/*Try the parent*/
|
||||
obj_act = lv_obj_get_parent(obj_act);
|
||||
}
|
||||
|
||||
/*Use the last candidate*/
|
||||
if(obj_candidate) {
|
||||
proc->types.pointer.scroll_dir = dir_candidate;
|
||||
proc->types.pointer.scroll_obj = obj_candidate;
|
||||
proc->types.pointer.scroll_sum.x = 0;
|
||||
proc->types.pointer.scroll_sum.y = 0;
|
||||
}
|
||||
|
||||
return obj_candidate;
|
||||
}
|
||||
|
||||
static void init_scroll_limits(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_obj_t * obj = proc->types.pointer.scroll_obj;
|
||||
/*If there no STOP allow scrolling anywhere*/
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLL_ONE) == false) {
|
||||
lv_area_set(&proc->types.pointer.scroll_area, LV_COORD_MIN, LV_COORD_MIN, LV_COORD_MAX, LV_COORD_MAX);
|
||||
}
|
||||
/*With STOP limit the scrolling to the perv and next snap point*/
|
||||
else {
|
||||
switch(lv_obj_get_scroll_snap_y(obj)) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y1 + 1, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y1 - 1, 0);
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y2, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y2, 0);
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER: {
|
||||
lv_coord_t y_mid = obj->coords.y1 + lv_area_get_height(&obj->coords) / 2;
|
||||
proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, y_mid + 1, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, y_mid - 1, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
proc->types.pointer.scroll_area.y1 = LV_COORD_MIN;
|
||||
proc->types.pointer.scroll_area.y2 = LV_COORD_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(lv_obj_get_scroll_snap_x(obj)) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, obj->coords.x1, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, obj->coords.x1, 0);
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, obj->coords.x2, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, obj->coords.x2, 0);
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER: {
|
||||
lv_coord_t x_mid = obj->coords.x1 + lv_area_get_width(&obj->coords) / 2;
|
||||
proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, x_mid + 1, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, x_mid - 1, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
proc->types.pointer.scroll_area.x1 = LV_COORD_MIN;
|
||||
proc->types.pointer.scroll_area.x2 = LV_COORD_MAX;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*Allow scrolling on the edges. It will be reverted to the edge due to snapping anyway*/
|
||||
if(proc->types.pointer.scroll_area.x1 == 0) proc->types.pointer.scroll_area.x1 = LV_COORD_MIN;
|
||||
if(proc->types.pointer.scroll_area.x2 == 0) proc->types.pointer.scroll_area.x2 = LV_COORD_MAX;
|
||||
if(proc->types.pointer.scroll_area.y1 == 0) proc->types.pointer.scroll_area.y1 = LV_COORD_MIN;
|
||||
if(proc->types.pointer.scroll_area.y2 == 0) proc->types.pointer.scroll_area.y2 = LV_COORD_MAX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for snap point in the `min` - `max` range.
|
||||
* @param obj the object on which snap point should be found
|
||||
* @param min ignore snap points smaller than this. (Absolute coordinate)
|
||||
* @param max ignore snap points greater than this. (Absolute coordinate)
|
||||
* @param ofs offset to snap points. Useful the get a snap point in an imagined case
|
||||
* what if children are already moved by this value
|
||||
* @return the distance of the snap point.
|
||||
*/
|
||||
static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs)
|
||||
{
|
||||
lv_scroll_snap_t align = lv_obj_get_scroll_snap_x(obj);
|
||||
if(align == LV_SCROLL_SNAP_NONE) return 0;
|
||||
|
||||
lv_coord_t dist = LV_COORD_MAX;
|
||||
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
|
||||
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) {
|
||||
lv_coord_t x_child = 0;
|
||||
lv_coord_t x_parent = 0;
|
||||
switch(align) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
x_child = child->coords.x1;
|
||||
x_parent = obj->coords.x1 + pad_left;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
x_child = child->coords.x2;
|
||||
x_parent = obj->coords.x2 - pad_right;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
x_child = child->coords.x1 + lv_area_get_width(&child->coords) / 2;
|
||||
x_parent = obj->coords.x1 + pad_left + (lv_area_get_width(&obj->coords) - pad_left - pad_right) / 2;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
x_child += ofs;
|
||||
if(x_child >= min && x_child <= max) {
|
||||
lv_coord_t x = x_child - x_parent;
|
||||
if(LV_ABS(x) < LV_ABS(dist)) dist = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dist == LV_COORD_MAX ? 0 : -dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for snap point in the `min` - `max` range.
|
||||
* @param obj the object on which snap point should be found
|
||||
* @param min ignore snap points smaller than this. (Absolute coordinate)
|
||||
* @param max ignore snap points greater than this. (Absolute coordinate)
|
||||
* @param ofs offset to snap points. Useful to get a snap point in an imagined case
|
||||
* what if children are already moved by this value
|
||||
* @return the distance of the snap point.
|
||||
*/
|
||||
static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs)
|
||||
{
|
||||
lv_scroll_snap_t align = lv_obj_get_scroll_snap_y(obj);
|
||||
if(align == LV_SCROLL_SNAP_NONE) return 0;
|
||||
|
||||
lv_coord_t dist = LV_COORD_MAX;
|
||||
|
||||
lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN);
|
||||
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) {
|
||||
lv_coord_t y_child = 0;
|
||||
lv_coord_t y_parent = 0;
|
||||
switch(align) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
y_child = child->coords.y1;
|
||||
y_parent = obj->coords.y1 + pad_top;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
y_child = child->coords.y2;
|
||||
y_parent = obj->coords.y2 - pad_bottom;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
y_child = child->coords.y1 + lv_area_get_height(&child->coords) / 2;
|
||||
y_parent = obj->coords.y1 + pad_top + (lv_area_get_height(&obj->coords) - pad_top - pad_bottom) / 2;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
y_child += ofs;
|
||||
if(y_child >= min && y_child <= max) {
|
||||
lv_coord_t y = y_child - y_parent;
|
||||
if(LV_ABS(y) < LV_ABS(dist)) dist = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dist == LV_COORD_MAX ? 0 : -dist;
|
||||
}
|
||||
|
||||
static void scroll_limit_diff(_lv_indev_proc_t * proc, lv_coord_t * diff_x, lv_coord_t * diff_y)
|
||||
{
|
||||
if(diff_y) {
|
||||
if(proc->types.pointer.scroll_sum.y + *diff_y < proc->types.pointer.scroll_area.y1) {
|
||||
*diff_y = proc->types.pointer.scroll_area.y1 - proc->types.pointer.scroll_sum.y;
|
||||
}
|
||||
|
||||
if(proc->types.pointer.scroll_sum.y + *diff_y > proc->types.pointer.scroll_area.y2) {
|
||||
*diff_y = proc->types.pointer.scroll_area.y2 - proc->types.pointer.scroll_sum.y;
|
||||
}
|
||||
}
|
||||
|
||||
if(diff_x) {
|
||||
if(proc->types.pointer.scroll_sum.x + *diff_x < proc->types.pointer.scroll_area.x1) {
|
||||
*diff_x = proc->types.pointer.scroll_area.x1 - proc->types.pointer.scroll_sum.x;
|
||||
}
|
||||
|
||||
if(proc->types.pointer.scroll_sum.x + *diff_x > proc->types.pointer.scroll_area.x2) {
|
||||
*diff_x = proc->types.pointer.scroll_area.x2 - proc->types.pointer.scroll_sum.x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static lv_coord_t scroll_throw_predict_y(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_coord_t y = proc->types.pointer.scroll_throw_vect.y;
|
||||
lv_coord_t move = 0;
|
||||
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
lv_coord_t scroll_throw = indev_act->driver->scroll_throw;
|
||||
|
||||
while(y) {
|
||||
move += y;
|
||||
y = y * (100 - scroll_throw) / 100;
|
||||
}
|
||||
return move;
|
||||
}
|
||||
|
||||
|
||||
static lv_coord_t scroll_throw_predict_x(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_coord_t x = proc->types.pointer.scroll_throw_vect.x;
|
||||
lv_coord_t move = 0;
|
||||
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
lv_coord_t scroll_throw = indev_act->driver->scroll_throw;
|
||||
|
||||
while(x) {
|
||||
move += x;
|
||||
x = x * (100 - scroll_throw) / 100;
|
||||
}
|
||||
return move;
|
||||
}
|
||||
|
||||
static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_t scroll_start, lv_coord_t scroll_end,
|
||||
lv_dir_t dir)
|
||||
{
|
||||
if(lv_obj_has_flag(scroll_obj, LV_OBJ_FLAG_SCROLL_ELASTIC)) {
|
||||
/*If there is snapping in the current direction don't use the elastic factor because
|
||||
*it's natural that the first and last items are scrolled (snapped) in.*/
|
||||
lv_scroll_snap_t snap;
|
||||
snap = dir == LV_DIR_HOR ? lv_obj_get_scroll_snap_x(scroll_obj) : lv_obj_get_scroll_snap_y(scroll_obj);
|
||||
|
||||
lv_obj_t * act_obj = lv_indev_get_obj_act();
|
||||
lv_coord_t snap_point = 0;
|
||||
lv_coord_t act_obj_point = 0;
|
||||
|
||||
if(dir == LV_DIR_HOR) {
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(scroll_obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_right = lv_obj_get_style_pad_right(scroll_obj, LV_PART_MAIN);
|
||||
|
||||
switch(snap) {
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
snap_point = pad_left + (lv_area_get_width(&scroll_obj->coords) - pad_left - pad_right) / 2 + scroll_obj->coords.x1;
|
||||
act_obj_point = lv_area_get_width(&act_obj->coords) / 2 + act_obj->coords.x1;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_START:
|
||||
snap_point = scroll_obj->coords.x1 + pad_left;
|
||||
act_obj_point = act_obj->coords.x1;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
snap_point = scroll_obj->coords.x2 - pad_right;
|
||||
act_obj_point = act_obj->coords.x2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_coord_t pad_top = lv_obj_get_style_pad_top(scroll_obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(scroll_obj, LV_PART_MAIN);
|
||||
|
||||
switch(snap) {
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
snap_point = pad_top + (lv_area_get_height(&scroll_obj->coords) - pad_top - pad_bottom) / 2 + scroll_obj->coords.y1;
|
||||
act_obj_point = lv_area_get_height(&act_obj->coords) / 2 + act_obj->coords.y1;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_START:
|
||||
snap_point = scroll_obj->coords.y1 + pad_top;
|
||||
act_obj_point = act_obj->coords.y1;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
snap_point = scroll_obj->coords.y2 - pad_bottom;
|
||||
act_obj_point = act_obj->coords.y2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(scroll_end < 0) {
|
||||
if(snap != LV_SCROLL_SNAP_NONE && act_obj_point > snap_point) return diff;
|
||||
|
||||
/*Rounding*/
|
||||
if(diff < 0) diff -= ELASTIC_SLOWNESS_FACTOR / 2;
|
||||
if(diff > 0) diff += ELASTIC_SLOWNESS_FACTOR / 2;
|
||||
return diff / ELASTIC_SLOWNESS_FACTOR;
|
||||
}
|
||||
else if(scroll_start < 0) {
|
||||
if(snap != LV_SCROLL_SNAP_NONE && act_obj_point < snap_point) return diff;
|
||||
|
||||
/*Rounding*/
|
||||
if(diff < 0) diff -= ELASTIC_SLOWNESS_FACTOR / 2;
|
||||
if(diff > 0) diff += ELASTIC_SLOWNESS_FACTOR / 2;
|
||||
return diff / ELASTIC_SLOWNESS_FACTOR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*Scroll back to the boundary if required*/
|
||||
if(scroll_end + diff < 0) diff = - scroll_end;
|
||||
if(scroll_start - diff < 0) diff = scroll_start;
|
||||
}
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
|
||||
@@ -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*/
|
||||
948
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj.c
Normal file
948
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj.c
Normal file
@@ -0,0 +1,948 @@
|
||||
/**
|
||||
* @file lv_obj.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "lv_indev.h"
|
||||
#include "lv_refr.h"
|
||||
#include "lv_group.h"
|
||||
#include "lv_disp.h"
|
||||
#include "lv_theme.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "../draw/lv_draw.h"
|
||||
#include "../misc/lv_anim.h"
|
||||
#include "../misc/lv_timer.h"
|
||||
#include "../misc/lv_async.h"
|
||||
#include "../misc/lv_fs.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../misc/lv_log.h"
|
||||
#include "../hal/lv_hal.h"
|
||||
#include "../extra/lv_extra.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if LV_USE_GPU_STM32_DMA2D
|
||||
#include "../draw/stm32_dma2d/lv_gpu_stm32_dma2d.h"
|
||||
#endif
|
||||
|
||||
#if LV_USE_GPU_SWM341_DMA2D
|
||||
#include "../draw/swm341_dma2d/lv_gpu_swm341_dma2d.h"
|
||||
#endif
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT
|
||||
#include "../draw/nxp/pxp/lv_gpu_nxp_pxp.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
#define LV_OBJ_DEF_WIDTH (LV_DPX(100))
|
||||
#define LV_OBJ_DEF_HEIGHT (LV_DPX(50))
|
||||
#define STYLE_TRANSITION_MAX 32
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_obj_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
static void lv_obj_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
static void lv_obj_draw(lv_event_t * e);
|
||||
static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e);
|
||||
static void draw_scrollbar(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx);
|
||||
static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc);
|
||||
static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find);
|
||||
static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static bool lv_initialized = false;
|
||||
const lv_obj_class_t lv_obj_class = {
|
||||
.constructor_cb = lv_obj_constructor,
|
||||
.destructor_cb = lv_obj_destructor,
|
||||
.event_cb = lv_obj_event,
|
||||
.width_def = LV_DPI_DEF,
|
||||
.height_def = LV_DPI_DEF,
|
||||
.editable = LV_OBJ_CLASS_EDITABLE_FALSE,
|
||||
.group_def = LV_OBJ_CLASS_GROUP_DEF_FALSE,
|
||||
.instance_size = (sizeof(lv_obj_t)),
|
||||
.base_class = NULL,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
bool lv_is_initialized(void)
|
||||
{
|
||||
return lv_initialized;
|
||||
}
|
||||
|
||||
void lv_init(void)
|
||||
{
|
||||
/*Do nothing if already initialized*/
|
||||
if(lv_initialized) {
|
||||
LV_LOG_WARN("lv_init: already inited");
|
||||
return;
|
||||
}
|
||||
|
||||
LV_LOG_INFO("begin");
|
||||
|
||||
/*Initialize the misc modules*/
|
||||
lv_mem_init();
|
||||
|
||||
_lv_timer_core_init();
|
||||
|
||||
_lv_fs_init();
|
||||
|
||||
_lv_anim_core_init();
|
||||
|
||||
_lv_group_init();
|
||||
|
||||
lv_draw_init();
|
||||
|
||||
#if LV_USE_GPU_STM32_DMA2D
|
||||
/*Initialize DMA2D GPU*/
|
||||
lv_draw_stm32_dma2d_init();
|
||||
#endif
|
||||
|
||||
#if LV_USE_GPU_SWM341_DMA2D
|
||||
/*Initialize DMA2D GPU*/
|
||||
lv_draw_swm341_dma2d_init();
|
||||
#endif
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT
|
||||
PXP_COND_STOP(!lv_gpu_nxp_pxp_init(), "PXP init failed.");
|
||||
#endif
|
||||
|
||||
_lv_obj_style_init();
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_disp_ll), sizeof(lv_disp_t));
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_indev_ll), sizeof(lv_indev_t));
|
||||
|
||||
/*Initialize the screen refresh system*/
|
||||
_lv_refr_init();
|
||||
|
||||
_lv_img_decoder_init();
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
lv_img_cache_set_size(LV_IMG_CACHE_DEF_SIZE);
|
||||
#endif
|
||||
/*Test if the IDE has UTF-8 encoding*/
|
||||
char * txt = "Á";
|
||||
|
||||
uint8_t * txt_u8 = (uint8_t *)txt;
|
||||
if(txt_u8[0] != 0xc3 || txt_u8[1] != 0x81 || txt_u8[2] != 0x00) {
|
||||
LV_LOG_WARN("The strings have no UTF-8 encoding. Non-ASCII characters won't be displayed.");
|
||||
}
|
||||
|
||||
uint32_t endianess_test = 0x11223344;
|
||||
uint8_t * endianess_test_p = (uint8_t *) &endianess_test;
|
||||
bool big_endian = endianess_test_p[0] == 0x11 ? true : false;
|
||||
|
||||
if(big_endian) {
|
||||
LV_ASSERT_MSG(LV_BIG_ENDIAN_SYSTEM == 1,
|
||||
"It's a big endian system but LV_BIG_ENDIAN_SYSTEM is not enabled in lv_conf.h");
|
||||
}
|
||||
else {
|
||||
LV_ASSERT_MSG(LV_BIG_ENDIAN_SYSTEM == 0,
|
||||
"It's a little endian system but LV_BIG_ENDIAN_SYSTEM is enabled in lv_conf.h");
|
||||
}
|
||||
|
||||
#if LV_USE_ASSERT_MEM_INTEGRITY
|
||||
LV_LOG_WARN("Memory integrity checks are enabled via LV_USE_ASSERT_MEM_INTEGRITY which makes LVGL much slower");
|
||||
#endif
|
||||
|
||||
#if LV_USE_ASSERT_OBJ
|
||||
LV_LOG_WARN("Object sanity checks are enabled via LV_USE_ASSERT_OBJ which makes LVGL much slower");
|
||||
#endif
|
||||
|
||||
#if LV_USE_ASSERT_STYLE
|
||||
LV_LOG_WARN("Style sanity checks are enabled that uses more RAM");
|
||||
#endif
|
||||
|
||||
#if LV_LOG_LEVEL == LV_LOG_LEVEL_TRACE
|
||||
LV_LOG_WARN("Log level is set to 'Trace' which makes LVGL much slower");
|
||||
#endif
|
||||
|
||||
lv_extra_init();
|
||||
|
||||
lv_initialized = true;
|
||||
|
||||
LV_LOG_TRACE("finished");
|
||||
}
|
||||
|
||||
#if LV_ENABLE_GC || !LV_MEM_CUSTOM
|
||||
|
||||
void lv_deinit(void)
|
||||
{
|
||||
_lv_gc_clear_roots();
|
||||
|
||||
lv_disp_set_default(NULL);
|
||||
lv_mem_deinit();
|
||||
lv_initialized = false;
|
||||
|
||||
LV_LOG_INFO("lv_deinit done");
|
||||
|
||||
#if LV_USE_LOG
|
||||
lv_log_register_print_cb(NULL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
lv_obj_t * lv_obj_create(lv_obj_t * parent)
|
||||
{
|
||||
LV_LOG_INFO("begin");
|
||||
lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
|
||||
lv_obj_class_init_obj(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/*-----------------
|
||||
* Attribute set
|
||||
*----------------*/
|
||||
|
||||
void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
bool was_on_layout = lv_obj_is_layout_positioned(obj);
|
||||
|
||||
if(f & LV_OBJ_FLAG_HIDDEN) lv_obj_invalidate(obj);
|
||||
|
||||
obj->flags |= f;
|
||||
|
||||
if(f & LV_OBJ_FLAG_HIDDEN) {
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
if((was_on_layout != lv_obj_is_layout_positioned(obj)) || (f & (LV_OBJ_FLAG_LAYOUT_1 | LV_OBJ_FLAG_LAYOUT_2))) {
|
||||
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
}
|
||||
|
||||
if(f & LV_OBJ_FLAG_SCROLLABLE) {
|
||||
lv_area_t hor_area, ver_area;
|
||||
lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area);
|
||||
lv_obj_invalidate_area(obj, &hor_area);
|
||||
lv_obj_invalidate_area(obj, &ver_area);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
bool was_on_layout = lv_obj_is_layout_positioned(obj);
|
||||
if(f & LV_OBJ_FLAG_SCROLLABLE) {
|
||||
lv_area_t hor_area, ver_area;
|
||||
lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area);
|
||||
lv_obj_invalidate_area(obj, &hor_area);
|
||||
lv_obj_invalidate_area(obj, &ver_area);
|
||||
}
|
||||
|
||||
obj->flags &= (~f);
|
||||
|
||||
if(f & LV_OBJ_FLAG_HIDDEN) {
|
||||
lv_obj_invalidate(obj);
|
||||
if(lv_obj_is_layout_positioned(obj)) {
|
||||
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
}
|
||||
}
|
||||
|
||||
if((was_on_layout != lv_obj_is_layout_positioned(obj)) || (f & (LV_OBJ_FLAG_LAYOUT_1 | LV_OBJ_FLAG_LAYOUT_2))) {
|
||||
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void lv_obj_add_state(lv_obj_t * obj, lv_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_state_t new_state = obj->state | state;
|
||||
if(obj->state != new_state) {
|
||||
lv_obj_set_state(obj, new_state);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_state_t new_state = obj->state & (~state);
|
||||
if(obj->state != new_state) {
|
||||
lv_obj_set_state(obj, new_state);
|
||||
}
|
||||
}
|
||||
|
||||
/*=======================
|
||||
* Getter functions
|
||||
*======================*/
|
||||
|
||||
bool lv_obj_has_flag(const lv_obj_t * obj, lv_obj_flag_t f)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return (obj->flags & f) == f ? true : false;
|
||||
}
|
||||
|
||||
bool lv_obj_has_flag_any(const lv_obj_t * obj, lv_obj_flag_t f)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return (obj->flags & f) ? true : false;
|
||||
}
|
||||
|
||||
lv_state_t lv_obj_get_state(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return obj->state;
|
||||
}
|
||||
|
||||
bool lv_obj_has_state(const lv_obj_t * obj, lv_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return obj->state & state ? true : false;
|
||||
}
|
||||
|
||||
void * lv_obj_get_group(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(obj->spec_attr) return obj->spec_attr->group_p;
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
/*-------------------
|
||||
* OTHER FUNCTIONS
|
||||
*------------------*/
|
||||
|
||||
void lv_obj_allocate_spec_attr(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(obj->spec_attr == NULL) {
|
||||
static uint32_t x = 0;
|
||||
x++;
|
||||
obj->spec_attr = lv_mem_alloc(sizeof(_lv_obj_spec_attr_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr);
|
||||
if(obj->spec_attr == NULL) return;
|
||||
|
||||
lv_memset_00(obj->spec_attr, sizeof(_lv_obj_spec_attr_t));
|
||||
|
||||
obj->spec_attr->scroll_dir = LV_DIR_ALL;
|
||||
obj->spec_attr->scrollbar_mode = LV_SCROLLBAR_MODE_AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
bool lv_obj_check_type(const lv_obj_t * obj, const lv_obj_class_t * class_p)
|
||||
{
|
||||
if(obj == NULL) return false;
|
||||
return obj->class_p == class_p ? true : false;
|
||||
}
|
||||
|
||||
bool lv_obj_has_class(const lv_obj_t * obj, const lv_obj_class_t * class_p)
|
||||
{
|
||||
const lv_obj_class_t * obj_class = obj->class_p;
|
||||
while(obj_class) {
|
||||
if(obj_class == class_p) return true;
|
||||
obj_class = obj_class->base_class;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj)
|
||||
{
|
||||
return obj->class_p;
|
||||
}
|
||||
|
||||
bool lv_obj_is_valid(const lv_obj_t * obj)
|
||||
{
|
||||
lv_disp_t * disp = lv_disp_get_next(NULL);
|
||||
while(disp) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < disp->screen_cnt; i++) {
|
||||
if(disp->screens[i] == obj) return true;
|
||||
bool found = obj_valid_child(disp->screens[i], obj);
|
||||
if(found) return true;
|
||||
}
|
||||
|
||||
disp = lv_disp_get_next(disp);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_obj_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
LV_TRACE_OBJ_CREATE("begin");
|
||||
|
||||
lv_obj_t * parent = obj->parent;
|
||||
if(parent) {
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(parent);
|
||||
lv_coord_t st = lv_obj_get_scroll_top(parent);
|
||||
|
||||
obj->coords.y1 = parent->coords.y1 + lv_obj_get_style_pad_top(parent, LV_PART_MAIN) - st;
|
||||
obj->coords.y2 = obj->coords.y1 - 1;
|
||||
obj->coords.x1 = parent->coords.x1 + lv_obj_get_style_pad_left(parent, LV_PART_MAIN) - sl;
|
||||
obj->coords.x2 = obj->coords.x1 - 1;
|
||||
}
|
||||
|
||||
/*Set attributes*/
|
||||
obj->flags = LV_OBJ_FLAG_CLICKABLE;
|
||||
obj->flags |= LV_OBJ_FLAG_SNAPPABLE;
|
||||
if(parent) obj->flags |= LV_OBJ_FLAG_PRESS_LOCK;
|
||||
if(parent) obj->flags |= LV_OBJ_FLAG_SCROLL_CHAIN;
|
||||
obj->flags |= LV_OBJ_FLAG_CLICK_FOCUSABLE;
|
||||
obj->flags |= LV_OBJ_FLAG_SCROLLABLE;
|
||||
obj->flags |= LV_OBJ_FLAG_SCROLL_ELASTIC;
|
||||
obj->flags |= LV_OBJ_FLAG_SCROLL_MOMENTUM;
|
||||
obj->flags |= LV_OBJ_FLAG_SCROLL_WITH_ARROW;
|
||||
if(parent) obj->flags |= LV_OBJ_FLAG_GESTURE_BUBBLE;
|
||||
|
||||
LV_TRACE_OBJ_CREATE("finished");
|
||||
}
|
||||
|
||||
static void lv_obj_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
|
||||
_lv_event_mark_deleted(obj);
|
||||
|
||||
/*Remove all style*/
|
||||
lv_obj_enable_style_refresh(false); /*No need to refresh the style because the object will be deleted*/
|
||||
lv_obj_remove_style_all(obj);
|
||||
lv_obj_enable_style_refresh(true);
|
||||
|
||||
/*Remove the animations from this object*/
|
||||
lv_anim_del(obj, NULL);
|
||||
|
||||
/*Delete from the group*/
|
||||
lv_group_t * group = lv_obj_get_group(obj);
|
||||
if(group) lv_group_remove_obj(obj);
|
||||
|
||||
if(obj->spec_attr) {
|
||||
if(obj->spec_attr->children) {
|
||||
lv_mem_free(obj->spec_attr->children);
|
||||
obj->spec_attr->children = NULL;
|
||||
}
|
||||
if(obj->spec_attr->event_dsc) {
|
||||
lv_mem_free(obj->spec_attr->event_dsc);
|
||||
obj->spec_attr->event_dsc = NULL;
|
||||
}
|
||||
|
||||
lv_mem_free(obj->spec_attr);
|
||||
obj->spec_attr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void lv_obj_draw(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * obj = lv_event_get_target(e);
|
||||
if(code == LV_EVENT_COVER_CHECK) {
|
||||
lv_cover_check_info_t * info = lv_event_get_param(e);
|
||||
if(info->res == LV_COVER_RES_MASKED) return;
|
||||
if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) {
|
||||
info->res = LV_COVER_RES_MASKED;
|
||||
return;
|
||||
}
|
||||
|
||||
/*Most trivial test. Is the mask fully IN the object? If no it surely doesn't cover it*/
|
||||
lv_coord_t r = lv_obj_get_style_radius(obj, LV_PART_MAIN);
|
||||
lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN);
|
||||
lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN);
|
||||
lv_area_t coords;
|
||||
lv_area_copy(&coords, &obj->coords);
|
||||
coords.x1 -= w;
|
||||
coords.x2 += w;
|
||||
coords.y1 -= h;
|
||||
coords.y2 += h;
|
||||
|
||||
if(_lv_area_is_in(info->area, &coords, r) == false) {
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
if(lv_obj_get_style_bg_opa(obj, LV_PART_MAIN) < LV_OPA_MAX) {
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
info->res = LV_COVER_RES_COVER;
|
||||
|
||||
}
|
||||
else if(code == LV_EVENT_DRAW_MAIN) {
|
||||
lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e);
|
||||
lv_draw_rect_dsc_t draw_dsc;
|
||||
lv_draw_rect_dsc_init(&draw_dsc);
|
||||
/*If the border is drawn later disable loading its properties*/
|
||||
if(lv_obj_get_style_border_post(obj, LV_PART_MAIN)) {
|
||||
draw_dsc.border_post = 1;
|
||||
}
|
||||
|
||||
lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &draw_dsc);
|
||||
lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN);
|
||||
lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN);
|
||||
lv_area_t coords;
|
||||
lv_area_copy(&coords, &obj->coords);
|
||||
coords.x1 -= w;
|
||||
coords.x2 += w;
|
||||
coords.y1 -= h;
|
||||
coords.y2 += h;
|
||||
|
||||
lv_obj_draw_part_dsc_t part_dsc;
|
||||
lv_obj_draw_dsc_init(&part_dsc, draw_ctx);
|
||||
part_dsc.class_p = MY_CLASS;
|
||||
part_dsc.type = LV_OBJ_DRAW_PART_RECTANGLE;
|
||||
part_dsc.rect_dsc = &draw_dsc;
|
||||
part_dsc.draw_area = &coords;
|
||||
part_dsc.part = LV_PART_MAIN;
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc);
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
/*With clip corner enabled draw the bg img separately to make it clipped*/
|
||||
bool clip_corner = (lv_obj_get_style_clip_corner(obj, LV_PART_MAIN) && draw_dsc.radius != 0) ? true : false;
|
||||
const void * bg_img_src = draw_dsc.bg_img_src;
|
||||
if(clip_corner) {
|
||||
draw_dsc.bg_img_src = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
lv_draw_rect(draw_ctx, &draw_dsc, &coords);
|
||||
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(clip_corner) {
|
||||
lv_draw_mask_radius_param_t * mp = lv_mem_buf_get(sizeof(lv_draw_mask_radius_param_t));
|
||||
lv_draw_mask_radius_init(mp, &obj->coords, draw_dsc.radius, false);
|
||||
/*Add the mask and use `obj+8` as custom id. Don't use `obj` directly because it might be used by the user*/
|
||||
lv_draw_mask_add(mp, obj + 8);
|
||||
|
||||
if(bg_img_src) {
|
||||
draw_dsc.bg_opa = LV_OPA_TRANSP;
|
||||
draw_dsc.border_opa = LV_OPA_TRANSP;
|
||||
draw_dsc.outline_opa = LV_OPA_TRANSP;
|
||||
draw_dsc.shadow_opa = LV_OPA_TRANSP;
|
||||
draw_dsc.bg_img_src = bg_img_src;
|
||||
lv_draw_rect(draw_ctx, &draw_dsc, &coords);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc);
|
||||
}
|
||||
else if(code == LV_EVENT_DRAW_POST) {
|
||||
lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e);
|
||||
draw_scrollbar(obj, draw_ctx);
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) {
|
||||
lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8);
|
||||
if(param) {
|
||||
lv_draw_mask_free_param(param);
|
||||
lv_mem_buf_release(param);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*If the border is drawn later disable loading other properties*/
|
||||
if(lv_obj_get_style_border_post(obj, LV_PART_MAIN)) {
|
||||
lv_draw_rect_dsc_t draw_dsc;
|
||||
lv_draw_rect_dsc_init(&draw_dsc);
|
||||
draw_dsc.bg_opa = LV_OPA_TRANSP;
|
||||
draw_dsc.bg_img_opa = LV_OPA_TRANSP;
|
||||
draw_dsc.outline_opa = LV_OPA_TRANSP;
|
||||
draw_dsc.shadow_opa = LV_OPA_TRANSP;
|
||||
lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &draw_dsc);
|
||||
|
||||
lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN);
|
||||
lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN);
|
||||
lv_area_t coords;
|
||||
lv_area_copy(&coords, &obj->coords);
|
||||
coords.x1 -= w;
|
||||
coords.x2 += w;
|
||||
coords.y1 -= h;
|
||||
coords.y2 += h;
|
||||
|
||||
lv_obj_draw_part_dsc_t part_dsc;
|
||||
lv_obj_draw_dsc_init(&part_dsc, draw_ctx);
|
||||
part_dsc.class_p = MY_CLASS;
|
||||
part_dsc.type = LV_OBJ_DRAW_PART_BORDER_POST;
|
||||
part_dsc.rect_dsc = &draw_dsc;
|
||||
part_dsc.draw_area = &coords;
|
||||
part_dsc.part = LV_PART_MAIN;
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc);
|
||||
|
||||
lv_draw_rect(draw_ctx, &draw_dsc, &coords);
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_scrollbar(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
|
||||
lv_area_t hor_area;
|
||||
lv_area_t ver_area;
|
||||
lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area);
|
||||
|
||||
if(lv_area_get_size(&hor_area) <= 0 && lv_area_get_size(&ver_area) <= 0) return;
|
||||
|
||||
lv_draw_rect_dsc_t draw_dsc;
|
||||
lv_res_t sb_res = scrollbar_init_draw_dsc(obj, &draw_dsc);
|
||||
if(sb_res != LV_RES_OK) return;
|
||||
|
||||
lv_obj_draw_part_dsc_t part_dsc;
|
||||
lv_obj_draw_dsc_init(&part_dsc, draw_ctx);
|
||||
part_dsc.class_p = MY_CLASS;
|
||||
part_dsc.type = LV_OBJ_DRAW_PART_SCROLLBAR;
|
||||
part_dsc.rect_dsc = &draw_dsc;
|
||||
part_dsc.part = LV_PART_SCROLLBAR;
|
||||
|
||||
if(lv_area_get_size(&hor_area) > 0) {
|
||||
part_dsc.draw_area = &hor_area;
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc);
|
||||
lv_draw_rect(draw_ctx, &draw_dsc, &hor_area);
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc);
|
||||
}
|
||||
if(lv_area_get_size(&ver_area) > 0) {
|
||||
part_dsc.draw_area = &ver_area;
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc);
|
||||
part_dsc.draw_area = &ver_area;
|
||||
lv_draw_rect(draw_ctx, &draw_dsc, &ver_area);
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the draw descriptor for the scrollbar
|
||||
* @param obj pointer to an object
|
||||
* @param dsc the draw descriptor to initialize
|
||||
* @return LV_RES_OK: the scrollbar is visible; LV_RES_INV: the scrollbar is not visible
|
||||
*/
|
||||
static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
lv_draw_rect_dsc_init(dsc);
|
||||
dsc->bg_opa = lv_obj_get_style_bg_opa(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->bg_opa > LV_OPA_MIN) {
|
||||
dsc->bg_color = lv_obj_get_style_bg_color(obj, LV_PART_SCROLLBAR);
|
||||
}
|
||||
|
||||
dsc->border_opa = lv_obj_get_style_border_opa(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->border_opa > LV_OPA_MIN) {
|
||||
dsc->border_width = lv_obj_get_style_border_width(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->border_width > 0) {
|
||||
dsc->border_color = lv_obj_get_style_border_color(obj, LV_PART_SCROLLBAR);
|
||||
}
|
||||
else {
|
||||
dsc->border_opa = LV_OPA_TRANSP;
|
||||
}
|
||||
}
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
dsc->shadow_opa = lv_obj_get_style_shadow_opa(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->shadow_opa > LV_OPA_MIN) {
|
||||
dsc->shadow_width = lv_obj_get_style_shadow_width(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->shadow_width > 0) {
|
||||
dsc->shadow_spread = lv_obj_get_style_shadow_spread(obj, LV_PART_SCROLLBAR);
|
||||
dsc->shadow_color = lv_obj_get_style_shadow_color(obj, LV_PART_SCROLLBAR);
|
||||
}
|
||||
else {
|
||||
dsc->shadow_opa = LV_OPA_TRANSP;
|
||||
}
|
||||
}
|
||||
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, LV_PART_SCROLLBAR);
|
||||
if(opa < LV_OPA_MAX) {
|
||||
dsc->bg_opa = (dsc->bg_opa * opa) >> 8;
|
||||
dsc->border_opa = (dsc->bg_opa * opa) >> 8;
|
||||
dsc->shadow_opa = (dsc->bg_opa * opa) >> 8;
|
||||
}
|
||||
|
||||
if(dsc->bg_opa != LV_OPA_TRANSP || dsc->border_opa != LV_OPA_TRANSP || dsc->shadow_opa != LV_OPA_TRANSP) {
|
||||
dsc->radius = lv_obj_get_style_radius(obj, LV_PART_SCROLLBAR);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
else {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
#else
|
||||
if(dsc->bg_opa != LV_OPA_TRANSP || dsc->border_opa != LV_OPA_TRANSP) return LV_RES_OK;
|
||||
else return LV_RES_INV;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * obj = lv_event_get_current_target(e);
|
||||
if(code == LV_EVENT_PRESSED) {
|
||||
lv_obj_add_state(obj, LV_STATE_PRESSED);
|
||||
}
|
||||
else if(code == LV_EVENT_RELEASED) {
|
||||
lv_obj_clear_state(obj, LV_STATE_PRESSED);
|
||||
void * param = lv_event_get_param(e);
|
||||
/*Go the checked state if enabled*/
|
||||
if(lv_indev_get_scroll_obj(param) == NULL && lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) {
|
||||
if(!(lv_obj_get_state(obj) & LV_STATE_CHECKED)) lv_obj_add_state(obj, LV_STATE_CHECKED);
|
||||
else lv_obj_clear_state(obj, LV_STATE_CHECKED);
|
||||
|
||||
lv_res_t res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_PRESS_LOST) {
|
||||
lv_obj_clear_state(obj, LV_STATE_PRESSED);
|
||||
}
|
||||
else if(code == LV_EVENT_STYLE_CHANGED) {
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(uint32_t i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
lv_obj_mark_layout_as_dirty(child);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_KEY) {
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) {
|
||||
char c = *((char *)lv_event_get_param(e));
|
||||
if(c == LV_KEY_RIGHT || c == LV_KEY_UP) {
|
||||
lv_obj_add_state(obj, LV_STATE_CHECKED);
|
||||
}
|
||||
else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) {
|
||||
lv_obj_clear_state(obj, LV_STATE_CHECKED);
|
||||
}
|
||||
|
||||
/*With Enter LV_EVENT_RELEASED will send VALUE_CHANGE event*/
|
||||
if(c != LV_KEY_ENTER) {
|
||||
lv_res_t res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
}
|
||||
}
|
||||
else if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_WITH_ARROW) && !lv_obj_is_editable(obj)) {
|
||||
/*scroll by keypad or encoder*/
|
||||
lv_anim_enable_t anim_enable = LV_ANIM_OFF;
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(obj);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(obj);
|
||||
char c = *((char *)lv_event_get_param(e));
|
||||
if(c == LV_KEY_DOWN) {
|
||||
/*use scroll_to_x/y functions to enforce scroll limits*/
|
||||
lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) + lv_obj_get_height(obj) / 4, anim_enable);
|
||||
}
|
||||
else if(c == LV_KEY_UP) {
|
||||
lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) - lv_obj_get_height(obj) / 4, anim_enable);
|
||||
}
|
||||
else if(c == LV_KEY_RIGHT) {
|
||||
/*If the object can't be scrolled horizontally then scroll it vertically*/
|
||||
if(!((lv_obj_get_scroll_dir(obj) & LV_DIR_HOR) && (sl > 0 || sr > 0)))
|
||||
lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) + lv_obj_get_height(obj) / 4, anim_enable);
|
||||
else
|
||||
lv_obj_scroll_to_x(obj, lv_obj_get_scroll_x(obj) + lv_obj_get_width(obj) / 4, anim_enable);
|
||||
}
|
||||
else if(c == LV_KEY_LEFT) {
|
||||
/*If the object can't be scrolled horizontally then scroll it vertically*/
|
||||
if(!((lv_obj_get_scroll_dir(obj) & LV_DIR_HOR) && (sl > 0 || sr > 0)))
|
||||
lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) - lv_obj_get_height(obj) / 4, anim_enable);
|
||||
else
|
||||
lv_obj_scroll_to_x(obj, lv_obj_get_scroll_x(obj) - lv_obj_get_width(obj) / 4, anim_enable);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_FOCUSED) {
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS)) {
|
||||
lv_obj_scroll_to_view_recursive(obj, LV_ANIM_ON);
|
||||
}
|
||||
|
||||
bool editing = false;
|
||||
editing = lv_group_get_editing(lv_obj_get_group(obj));
|
||||
lv_state_t state = LV_STATE_FOCUSED;
|
||||
|
||||
/* Use the indev for then indev handler.
|
||||
* But if the obj was focused manually it returns NULL so try to
|
||||
* use the indev from the event*/
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
if(indev == NULL) indev = lv_event_get_indev(e);
|
||||
|
||||
lv_indev_type_t indev_type = lv_indev_get_type(indev);
|
||||
if(indev_type == LV_INDEV_TYPE_KEYPAD || indev_type == LV_INDEV_TYPE_ENCODER) state |= LV_STATE_FOCUS_KEY;
|
||||
if(editing) {
|
||||
state |= LV_STATE_EDITED;
|
||||
lv_obj_add_state(obj, state);
|
||||
}
|
||||
else {
|
||||
lv_obj_add_state(obj, state);
|
||||
lv_obj_clear_state(obj, LV_STATE_EDITED);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_SCROLL_BEGIN) {
|
||||
lv_obj_add_state(obj, LV_STATE_SCROLLED);
|
||||
}
|
||||
else if(code == LV_EVENT_SCROLL_END) {
|
||||
lv_obj_clear_state(obj, LV_STATE_SCROLLED);
|
||||
if(lv_obj_get_scrollbar_mode(obj) == LV_SCROLLBAR_MODE_ACTIVE) {
|
||||
lv_area_t hor_area, ver_area;
|
||||
lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area);
|
||||
lv_obj_invalidate_area(obj, &hor_area);
|
||||
lv_obj_invalidate_area(obj, &ver_area);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_DEFOCUSED) {
|
||||
lv_obj_clear_state(obj, LV_STATE_FOCUSED | LV_STATE_EDITED | LV_STATE_FOCUS_KEY);
|
||||
}
|
||||
else if(code == LV_EVENT_SIZE_CHANGED) {
|
||||
lv_coord_t align = lv_obj_get_style_align(obj, LV_PART_MAIN);
|
||||
uint16_t layout = lv_obj_get_style_layout(obj, LV_PART_MAIN);
|
||||
if(layout || align) {
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
}
|
||||
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
lv_obj_mark_layout_as_dirty(child);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_CHILD_CHANGED) {
|
||||
lv_coord_t w = lv_obj_get_style_width(obj, LV_PART_MAIN);
|
||||
lv_coord_t h = lv_obj_get_style_height(obj, LV_PART_MAIN);
|
||||
lv_coord_t align = lv_obj_get_style_align(obj, LV_PART_MAIN);
|
||||
uint16_t layout = lv_obj_get_style_layout(obj, LV_PART_MAIN);
|
||||
if(layout || align || w == LV_SIZE_CONTENT || h == LV_SIZE_CONTENT) {
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) {
|
||||
lv_coord_t d = lv_obj_calculate_ext_draw_size(obj, LV_PART_MAIN);
|
||||
lv_event_set_ext_draw_size(e, d);
|
||||
}
|
||||
else if(code == LV_EVENT_DRAW_MAIN || code == LV_EVENT_DRAW_POST || code == LV_EVENT_COVER_CHECK) {
|
||||
lv_obj_draw(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state (fully overwrite) of an object.
|
||||
* If specified in the styles, transition animations will be started from the previous state to the current.
|
||||
* @param obj pointer to an object
|
||||
* @param state the new state
|
||||
*/
|
||||
static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state)
|
||||
{
|
||||
if(obj->state == new_state) return;
|
||||
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_state_t prev_state = obj->state;
|
||||
obj->state = new_state;
|
||||
|
||||
_lv_style_state_cmp_t cmp_res = _lv_obj_style_state_compare(obj, prev_state, new_state);
|
||||
/*If there is no difference in styles there is nothing else to do*/
|
||||
if(cmp_res == _LV_STYLE_STATE_CMP_SAME) return;
|
||||
|
||||
_lv_obj_style_transition_dsc_t * ts = lv_mem_buf_get(sizeof(_lv_obj_style_transition_dsc_t) * STYLE_TRANSITION_MAX);
|
||||
lv_memset_00(ts, sizeof(_lv_obj_style_transition_dsc_t) * STYLE_TRANSITION_MAX);
|
||||
uint32_t tsi = 0;
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt && tsi < STYLE_TRANSITION_MAX; i++) {
|
||||
_lv_obj_style_t * obj_style = &obj->styles[i];
|
||||
lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector);
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector);
|
||||
if(state_act & (~new_state)) continue; /*Skip unrelated styles*/
|
||||
if(obj_style->is_trans) continue;
|
||||
|
||||
lv_style_value_t v;
|
||||
if(lv_style_get_prop_inlined(obj_style->style, LV_STYLE_TRANSITION, &v) != LV_STYLE_RES_FOUND) continue;
|
||||
const lv_style_transition_dsc_t * tr = v.ptr;
|
||||
|
||||
/*Add the props to the set if not added yet or added but with smaller weight*/
|
||||
uint32_t j;
|
||||
for(j = 0; tr->props[j] != 0 && tsi < STYLE_TRANSITION_MAX; j++) {
|
||||
uint32_t t;
|
||||
for(t = 0; t < tsi; t++) {
|
||||
lv_style_selector_t selector = ts[t].selector;
|
||||
lv_state_t state_ts = lv_obj_style_get_selector_state(selector);
|
||||
lv_part_t part_ts = lv_obj_style_get_selector_part(selector);
|
||||
if(ts[t].prop == tr->props[j] && part_ts == part_act && state_ts >= state_act) break;
|
||||
}
|
||||
|
||||
/*If not found add it*/
|
||||
if(t == tsi) {
|
||||
ts[tsi].time = tr->time;
|
||||
ts[tsi].delay = tr->delay;
|
||||
ts[tsi].path_cb = tr->path_xcb;
|
||||
ts[tsi].prop = tr->props[j];
|
||||
#if LV_USE_USER_DATA
|
||||
ts[tsi].user_data = tr->user_data;
|
||||
#endif
|
||||
ts[tsi].selector = obj_style->selector;
|
||||
tsi++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < tsi; i++) {
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(ts[i].selector);
|
||||
_lv_obj_style_create_transition(obj, part_act, prev_state, new_state, &ts[i]);
|
||||
}
|
||||
|
||||
lv_mem_buf_release(ts);
|
||||
|
||||
if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_REDRAW) {
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
else if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_LAYOUT) {
|
||||
lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
|
||||
}
|
||||
else if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD) {
|
||||
lv_obj_invalidate(obj);
|
||||
lv_obj_refresh_ext_draw_size(obj);
|
||||
}
|
||||
}
|
||||
|
||||
static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find)
|
||||
{
|
||||
/*Check all children of `parent`*/
|
||||
uint32_t child_cnt = 0;
|
||||
if(parent->spec_attr) child_cnt = parent->spec_attr->child_cnt;
|
||||
uint32_t i;
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = parent->spec_attr->children[i];
|
||||
if(child == obj_to_find) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*Check the children*/
|
||||
bool found = obj_valid_child(child, obj_to_find);
|
||||
if(found) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
409
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj.h
Normal file
409
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj.h
Normal file
@@ -0,0 +1,409 @@
|
||||
/**
|
||||
* @file lv_obj.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_H
|
||||
#define LV_OBJ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#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
|
||||
* Not all parts are 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 : 6; /**< Number of event callbacks stored in `event_dsc` array*/
|
||||
uint8_t layer_type : 2; /**< Cache the layer type here. Element of @lv_intermediate_layer_type_t */
|
||||
} _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*/
|
||||
202
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_class.c
Normal file
202
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_class.c
Normal file
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* @file lv_obj_class.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_obj_construct(lv_obj_t * obj);
|
||||
static uint32_t get_instance_size(const lv_obj_class_t * class_p);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * parent)
|
||||
{
|
||||
LV_TRACE_OBJ_CREATE("Creating object with %p class on %p parent", (void *)class_p, (void *)parent);
|
||||
uint32_t s = get_instance_size(class_p);
|
||||
lv_obj_t * obj = lv_mem_alloc(s);
|
||||
if(obj == NULL) return NULL;
|
||||
lv_memset_00(obj, s);
|
||||
obj->class_p = class_p;
|
||||
obj->parent = parent;
|
||||
|
||||
/*Create a screen*/
|
||||
if(parent == NULL) {
|
||||
LV_TRACE_OBJ_CREATE("creating a screen");
|
||||
lv_disp_t * disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("No display created yet. No place to assign the new screen");
|
||||
lv_mem_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(disp->screens == NULL) {
|
||||
disp->screens = lv_mem_alloc(sizeof(lv_obj_t *));
|
||||
disp->screens[0] = obj;
|
||||
disp->screen_cnt = 1;
|
||||
}
|
||||
else {
|
||||
disp->screen_cnt++;
|
||||
disp->screens = lv_mem_realloc(disp->screens, sizeof(lv_obj_t *) * disp->screen_cnt);
|
||||
disp->screens[disp->screen_cnt - 1] = obj;
|
||||
}
|
||||
|
||||
/*Set coordinates to full screen size*/
|
||||
obj->coords.x1 = 0;
|
||||
obj->coords.y1 = 0;
|
||||
obj->coords.x2 = lv_disp_get_hor_res(NULL) - 1;
|
||||
obj->coords.y2 = lv_disp_get_ver_res(NULL) - 1;
|
||||
}
|
||||
/*Create a normal object*/
|
||||
else {
|
||||
LV_TRACE_OBJ_CREATE("creating normal object");
|
||||
LV_ASSERT_OBJ(parent, MY_CLASS);
|
||||
if(parent->spec_attr == NULL) {
|
||||
lv_obj_allocate_spec_attr(parent);
|
||||
}
|
||||
|
||||
if(parent->spec_attr->children == NULL) {
|
||||
parent->spec_attr->children = lv_mem_alloc(sizeof(lv_obj_t *));
|
||||
parent->spec_attr->children[0] = obj;
|
||||
parent->spec_attr->child_cnt = 1;
|
||||
}
|
||||
else {
|
||||
parent->spec_attr->child_cnt++;
|
||||
parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children,
|
||||
sizeof(lv_obj_t *) * parent->spec_attr->child_cnt);
|
||||
parent->spec_attr->children[parent->spec_attr->child_cnt - 1] = obj;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void lv_obj_class_init_obj(lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
lv_obj_enable_style_refresh(false);
|
||||
|
||||
lv_theme_apply(obj);
|
||||
lv_obj_construct(obj);
|
||||
|
||||
lv_obj_enable_style_refresh(true);
|
||||
lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
|
||||
|
||||
lv_obj_refresh_self_size(obj);
|
||||
|
||||
lv_group_t * def_group = lv_group_get_default();
|
||||
if(def_group && lv_obj_is_group_def(obj)) {
|
||||
lv_group_add_obj(def_group, obj);
|
||||
}
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
if(parent) {
|
||||
/*Call the ancestor's event handler to the parent to notify it about the new child.
|
||||
*Also triggers layout update*/
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj);
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CREATED, obj);
|
||||
|
||||
/*Invalidate the area if not screen created*/
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void _lv_obj_destruct(lv_obj_t * obj)
|
||||
{
|
||||
if(obj->class_p->destructor_cb) obj->class_p->destructor_cb(obj->class_p, obj);
|
||||
|
||||
if(obj->class_p->base_class) {
|
||||
/*Don't let the descendant methods run during destructing the ancestor type*/
|
||||
obj->class_p = obj->class_p->base_class;
|
||||
|
||||
/*Call the base class's destructor too*/
|
||||
_lv_obj_destruct(obj);
|
||||
}
|
||||
}
|
||||
|
||||
bool lv_obj_is_editable(lv_obj_t * obj)
|
||||
{
|
||||
const lv_obj_class_t * class_p = obj->class_p;
|
||||
|
||||
/*Find a base in which editable is set*/
|
||||
while(class_p && class_p->editable == LV_OBJ_CLASS_EDITABLE_INHERIT) class_p = class_p->base_class;
|
||||
|
||||
if(class_p == NULL) return false;
|
||||
|
||||
return class_p->editable == LV_OBJ_CLASS_EDITABLE_TRUE ? true : false;
|
||||
}
|
||||
|
||||
bool lv_obj_is_group_def(lv_obj_t * obj)
|
||||
{
|
||||
const lv_obj_class_t * class_p = obj->class_p;
|
||||
|
||||
/*Find a base in which group_def is set*/
|
||||
while(class_p && class_p->group_def == LV_OBJ_CLASS_GROUP_DEF_INHERIT) class_p = class_p->base_class;
|
||||
|
||||
if(class_p == NULL) return false;
|
||||
|
||||
return class_p->group_def == LV_OBJ_CLASS_GROUP_DEF_TRUE ? true : false;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_obj_construct(lv_obj_t * obj)
|
||||
{
|
||||
const lv_obj_class_t * original_class_p = obj->class_p;
|
||||
|
||||
if(obj->class_p->base_class) {
|
||||
/*Don't let the descendant methods run during constructing the ancestor type*/
|
||||
obj->class_p = obj->class_p->base_class;
|
||||
|
||||
/*Construct the base first*/
|
||||
lv_obj_construct(obj);
|
||||
}
|
||||
|
||||
/*Restore the original class*/
|
||||
obj->class_p = original_class_p;
|
||||
|
||||
if(obj->class_p->constructor_cb) obj->class_p->constructor_cb(obj->class_p, obj);
|
||||
}
|
||||
|
||||
static uint32_t get_instance_size(const lv_obj_class_t * class_p)
|
||||
{
|
||||
/*Find a base in which instance size is set*/
|
||||
const lv_obj_class_t * base = class_p;
|
||||
while(base && base->instance_size == 0) base = base->base_class;
|
||||
|
||||
if(base == NULL) return 0; /*Never happens: set at least in `lv_obj` class*/
|
||||
|
||||
return base->instance_size;
|
||||
}
|
||||
@@ -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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*********************
|
||||
* 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*/
|
||||
406
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_draw.c
Normal file
406
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_draw.c
Normal file
@@ -0,0 +1,406 @@
|
||||
/**
|
||||
* @file lv_obj_draw.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj_draw.h"
|
||||
#include "lv_obj.h"
|
||||
#include "lv_disp.h"
|
||||
#include "lv_indev.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t * draw_dsc)
|
||||
{
|
||||
lv_opa_t opa = LV_OPA_COVER;
|
||||
if(part != LV_PART_MAIN) {
|
||||
opa = lv_obj_get_style_opa(obj, part);
|
||||
if(opa <= LV_OPA_MIN) {
|
||||
draw_dsc->bg_opa = LV_OPA_TRANSP;
|
||||
draw_dsc->bg_img_opa = LV_OPA_TRANSP;
|
||||
draw_dsc->border_opa = LV_OPA_TRANSP;
|
||||
draw_dsc->outline_opa = LV_OPA_TRANSP;
|
||||
draw_dsc->shadow_opa = LV_OPA_TRANSP;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
|
||||
draw_dsc->radius = lv_obj_get_style_radius(obj, part);
|
||||
|
||||
if(draw_dsc->bg_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->bg_opa = lv_obj_get_style_bg_opa(obj, part);
|
||||
if(draw_dsc->bg_opa > LV_OPA_MIN) {
|
||||
draw_dsc->bg_color = lv_obj_get_style_bg_color_filtered(obj, part);
|
||||
const lv_grad_dsc_t * grad = lv_obj_get_style_bg_grad(obj, part);
|
||||
if(grad && grad->dir != LV_GRAD_DIR_NONE) {
|
||||
lv_memcpy(&draw_dsc->bg_grad, grad, sizeof(*grad));
|
||||
}
|
||||
else {
|
||||
draw_dsc->bg_grad.dir = lv_obj_get_style_bg_grad_dir(obj, part);
|
||||
if(draw_dsc->bg_grad.dir != LV_GRAD_DIR_NONE) {
|
||||
draw_dsc->bg_grad.stops[0].color = lv_obj_get_style_bg_color_filtered(obj, part);
|
||||
draw_dsc->bg_grad.stops[1].color = lv_obj_get_style_bg_grad_color_filtered(obj, part);
|
||||
draw_dsc->bg_grad.stops[0].frac = lv_obj_get_style_bg_main_stop(obj, part);
|
||||
draw_dsc->bg_grad.stops[1].frac = lv_obj_get_style_bg_grad_stop(obj, part);
|
||||
}
|
||||
draw_dsc->bg_grad.dither = lv_obj_get_style_bg_dither_mode(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->border_width = lv_obj_get_style_border_width(obj, part);
|
||||
if(draw_dsc->border_width) {
|
||||
if(draw_dsc->border_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->border_opa = lv_obj_get_style_border_opa(obj, part);
|
||||
if(draw_dsc->border_opa > LV_OPA_MIN) {
|
||||
draw_dsc->border_side = lv_obj_get_style_border_side(obj, part);
|
||||
draw_dsc->border_color = lv_obj_get_style_border_color_filtered(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->outline_width = lv_obj_get_style_outline_width(obj, part);
|
||||
if(draw_dsc->outline_width) {
|
||||
if(draw_dsc->outline_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->outline_opa = lv_obj_get_style_outline_opa(obj, part);
|
||||
if(draw_dsc->outline_opa > LV_OPA_MIN) {
|
||||
draw_dsc->outline_pad = lv_obj_get_style_outline_pad(obj, part);
|
||||
draw_dsc->outline_color = lv_obj_get_style_outline_color_filtered(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(draw_dsc->bg_img_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->bg_img_src = lv_obj_get_style_bg_img_src(obj, part);
|
||||
if(draw_dsc->bg_img_src) {
|
||||
draw_dsc->bg_img_opa = lv_obj_get_style_bg_img_opa(obj, part);
|
||||
if(draw_dsc->bg_img_opa > LV_OPA_MIN) {
|
||||
if(lv_img_src_get_type(draw_dsc->bg_img_src) == LV_IMG_SRC_SYMBOL) {
|
||||
draw_dsc->bg_img_symbol_font = lv_obj_get_style_text_font(obj, part);
|
||||
draw_dsc->bg_img_recolor = lv_obj_get_style_text_color_filtered(obj, part);
|
||||
}
|
||||
else {
|
||||
draw_dsc->bg_img_recolor = lv_obj_get_style_bg_img_recolor_filtered(obj, part);
|
||||
draw_dsc->bg_img_recolor_opa = lv_obj_get_style_bg_img_recolor_opa(obj, part);
|
||||
draw_dsc->bg_img_tiled = lv_obj_get_style_bg_img_tiled(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(draw_dsc->shadow_opa) {
|
||||
draw_dsc->shadow_width = lv_obj_get_style_shadow_width(obj, part);
|
||||
if(draw_dsc->shadow_width) {
|
||||
if(draw_dsc->shadow_opa > LV_OPA_MIN) {
|
||||
draw_dsc->shadow_opa = lv_obj_get_style_shadow_opa(obj, part);
|
||||
if(draw_dsc->shadow_opa > LV_OPA_MIN) {
|
||||
draw_dsc->shadow_ofs_x = lv_obj_get_style_shadow_ofs_x(obj, part);
|
||||
draw_dsc->shadow_ofs_y = lv_obj_get_style_shadow_ofs_y(obj, part);
|
||||
draw_dsc->shadow_spread = lv_obj_get_style_shadow_spread(obj, part);
|
||||
draw_dsc->shadow_color = lv_obj_get_style_shadow_color_filtered(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else /*LV_DRAW_COMPLEX*/
|
||||
if(draw_dsc->bg_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->bg_opa = lv_obj_get_style_bg_opa(obj, part);
|
||||
if(draw_dsc->bg_opa > LV_OPA_MIN) {
|
||||
draw_dsc->bg_color = lv_obj_get_style_bg_color_filtered(obj, part);
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->border_width = lv_obj_get_style_border_width(obj, part);
|
||||
if(draw_dsc->border_width) {
|
||||
if(draw_dsc->border_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->border_opa = lv_obj_get_style_border_opa(obj, part);
|
||||
if(draw_dsc->border_opa > LV_OPA_MIN) {
|
||||
draw_dsc->border_color = lv_obj_get_style_border_color_filtered(obj, part);
|
||||
draw_dsc->border_side = lv_obj_get_style_border_side(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->outline_width = lv_obj_get_style_outline_width(obj, part);
|
||||
if(draw_dsc->outline_width) {
|
||||
if(draw_dsc->outline_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->outline_opa = lv_obj_get_style_outline_opa(obj, part);
|
||||
if(draw_dsc->outline_opa > LV_OPA_MIN) {
|
||||
draw_dsc->outline_pad = lv_obj_get_style_outline_pad(obj, part);
|
||||
draw_dsc->outline_color = lv_obj_get_style_outline_color_filtered(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(draw_dsc->bg_img_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->bg_img_src = lv_obj_get_style_bg_img_src(obj, part);
|
||||
if(draw_dsc->bg_img_src) {
|
||||
draw_dsc->bg_img_opa = lv_obj_get_style_bg_img_opa(obj, part);
|
||||
if(draw_dsc->bg_img_opa > LV_OPA_MIN) {
|
||||
if(lv_img_src_get_type(draw_dsc->bg_img_src) == LV_IMG_SRC_SYMBOL) {
|
||||
draw_dsc->bg_img_symbol_font = lv_obj_get_style_text_font(obj, part);
|
||||
draw_dsc->bg_img_recolor = lv_obj_get_style_text_color_filtered(obj, part);
|
||||
}
|
||||
else {
|
||||
draw_dsc->bg_img_recolor = lv_obj_get_style_bg_img_recolor_filtered(obj, part);
|
||||
draw_dsc->bg_img_recolor_opa = lv_obj_get_style_bg_img_recolor_opa(obj, part);
|
||||
draw_dsc->bg_img_tiled = lv_obj_get_style_bg_img_tiled(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(part != LV_PART_MAIN) {
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->bg_opa = (opa * draw_dsc->shadow_opa) >> 8;
|
||||
draw_dsc->bg_img_opa = (opa * draw_dsc->shadow_opa) >> 8;
|
||||
draw_dsc->border_opa = (opa * draw_dsc->shadow_opa) >> 8;
|
||||
draw_dsc->outline_opa = (opa * draw_dsc->shadow_opa) >> 8;
|
||||
draw_dsc->shadow_opa = (opa * draw_dsc->shadow_opa) >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc)
|
||||
{
|
||||
draw_dsc->opa = lv_obj_get_style_text_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
if(part != LV_PART_MAIN) {
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, part);
|
||||
if(opa <= LV_OPA_MIN) {
|
||||
draw_dsc->opa = LV_OPA_TRANSP;
|
||||
return;
|
||||
}
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->opa = (opa * draw_dsc->opa) >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->color = lv_obj_get_style_text_color_filtered(obj, part);
|
||||
draw_dsc->letter_space = lv_obj_get_style_text_letter_space(obj, part);
|
||||
draw_dsc->line_space = lv_obj_get_style_text_line_space(obj, part);
|
||||
draw_dsc->decor = lv_obj_get_style_text_decor(obj, part);
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
#endif
|
||||
|
||||
draw_dsc->font = lv_obj_get_style_text_font(obj, part);
|
||||
|
||||
#if LV_USE_BIDI
|
||||
draw_dsc->bidi_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN);
|
||||
#endif
|
||||
|
||||
draw_dsc->align = lv_obj_get_style_text_align(obj, part);
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_img_dsc(lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc)
|
||||
{
|
||||
draw_dsc->opa = lv_obj_get_style_img_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
if(part != LV_PART_MAIN) {
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, part);
|
||||
if(opa <= LV_OPA_MIN) {
|
||||
draw_dsc->opa = LV_OPA_TRANSP;
|
||||
return;
|
||||
}
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->opa = (opa * draw_dsc->opa) >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->angle = 0;
|
||||
draw_dsc->zoom = LV_IMG_ZOOM_NONE;
|
||||
draw_dsc->pivot.x = lv_area_get_width(&obj->coords) / 2;
|
||||
draw_dsc->pivot.y = lv_area_get_height(&obj->coords) / 2;
|
||||
|
||||
draw_dsc->recolor_opa = lv_obj_get_style_img_recolor_opa(obj, part);
|
||||
if(draw_dsc->recolor_opa > 0) {
|
||||
draw_dsc->recolor = lv_obj_get_style_img_recolor_filtered(obj, part);
|
||||
}
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_line_dsc(lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc)
|
||||
{
|
||||
draw_dsc->opa = lv_obj_get_style_line_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
if(part != LV_PART_MAIN) {
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, part);
|
||||
if(opa <= LV_OPA_MIN) {
|
||||
draw_dsc->opa = LV_OPA_TRANSP;
|
||||
return;
|
||||
}
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->opa = (opa * draw_dsc->opa) >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->width = lv_obj_get_style_line_width(obj, part);
|
||||
if(draw_dsc->width == 0) return;
|
||||
|
||||
draw_dsc->color = lv_obj_get_style_line_color_filtered(obj, part);
|
||||
|
||||
draw_dsc->dash_width = lv_obj_get_style_line_dash_width(obj, part);
|
||||
if(draw_dsc->dash_width) {
|
||||
draw_dsc->dash_gap = lv_obj_get_style_line_dash_gap(obj, part);
|
||||
}
|
||||
|
||||
draw_dsc->round_start = lv_obj_get_style_line_rounded(obj, part);
|
||||
draw_dsc->round_end = draw_dsc->round_start;
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc)
|
||||
{
|
||||
draw_dsc->width = lv_obj_get_style_arc_width(obj, part);
|
||||
if(draw_dsc->width == 0) return;
|
||||
|
||||
draw_dsc->opa = lv_obj_get_style_arc_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
if(part != LV_PART_MAIN) {
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, part);
|
||||
if(opa <= LV_OPA_MIN) {
|
||||
draw_dsc->opa = LV_OPA_TRANSP;
|
||||
return;
|
||||
}
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->opa = (opa * draw_dsc->opa) >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->color = lv_obj_get_style_arc_color_filtered(obj, part);
|
||||
draw_dsc->img_src = lv_obj_get_style_arc_img_src(obj, part);
|
||||
|
||||
draw_dsc->rounded = lv_obj_get_style_arc_rounded(obj, part);
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
#endif
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_calculate_ext_draw_size(lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_coord_t s = 0;
|
||||
|
||||
lv_coord_t sh_width = lv_obj_get_style_shadow_width(obj, part);
|
||||
if(sh_width) {
|
||||
lv_opa_t sh_opa = lv_obj_get_style_shadow_opa(obj, part);
|
||||
if(sh_opa > LV_OPA_MIN) {
|
||||
sh_width = sh_width / 2 + 1; /*The blur adds only half width*/
|
||||
sh_width += lv_obj_get_style_shadow_spread(obj, part);
|
||||
lv_coord_t sh_ofs_x = lv_obj_get_style_shadow_ofs_x(obj, part);
|
||||
lv_coord_t sh_ofs_y = lv_obj_get_style_shadow_ofs_y(obj, part);
|
||||
sh_width += LV_MAX(LV_ABS(sh_ofs_x), LV_ABS(sh_ofs_y));
|
||||
s = LV_MAX(s, sh_width);
|
||||
}
|
||||
}
|
||||
|
||||
lv_coord_t outline_width = lv_obj_get_style_outline_width(obj, part);
|
||||
if(outline_width) {
|
||||
lv_opa_t outline_opa = lv_obj_get_style_outline_opa(obj, part);
|
||||
if(outline_opa > LV_OPA_MIN) {
|
||||
lv_coord_t outline_pad = lv_obj_get_style_outline_pad(obj, part);
|
||||
s = LV_MAX(s, outline_pad + outline_width);
|
||||
}
|
||||
}
|
||||
|
||||
lv_coord_t w = lv_obj_get_style_transform_width(obj, part);
|
||||
lv_coord_t h = lv_obj_get_style_transform_height(obj, part);
|
||||
lv_coord_t wh = LV_MAX(w, h);
|
||||
if(wh > 0) s += wh;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_obj_draw_part_dsc_t));
|
||||
dsc->draw_ctx = draw_ctx;
|
||||
}
|
||||
|
||||
bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const lv_obj_class_t * class_p, uint32_t type)
|
||||
{
|
||||
if(dsc->class_p == class_p && dsc->type == type) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
void lv_obj_refresh_ext_draw_size(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_coord_t s_old = _lv_obj_get_ext_draw_size(obj);
|
||||
lv_coord_t s_new = 0;
|
||||
lv_event_send(obj, LV_EVENT_REFR_EXT_DRAW_SIZE, &s_new);
|
||||
|
||||
if(s_new != s_old) lv_obj_invalidate(obj);
|
||||
|
||||
/*Store the result if the special attrs already allocated*/
|
||||
if(obj->spec_attr) {
|
||||
obj->spec_attr->ext_draw_size = s_new;
|
||||
}
|
||||
/*Allocate spec. attrs. only if the result is not zero.
|
||||
*Zero is the default value if the spec. attr. are not defined.*/
|
||||
else if(s_new != 0) {
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
obj->spec_attr->ext_draw_size = s_new;
|
||||
}
|
||||
|
||||
if(s_new != s_old) lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
lv_coord_t _lv_obj_get_ext_draw_size(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return obj->spec_attr->ext_draw_size;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
lv_layer_type_t _lv_obj_get_layer_type(const lv_obj_t * obj)
|
||||
{
|
||||
|
||||
if(obj->spec_attr) return obj->spec_attr->layer_type;
|
||||
else return LV_LAYER_TYPE_NONE;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
172
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_draw.h
Normal file
172
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_draw.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* @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 enum {
|
||||
LV_LAYER_TYPE_NONE,
|
||||
LV_LAYER_TYPE_SIMPLE,
|
||||
LV_LAYER_TYPE_TRANSFORM,
|
||||
} lv_layer_type_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_<name>_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_EVENT_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_<name>_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);
|
||||
|
||||
|
||||
lv_layer_type_t _lv_obj_get_layer_type(const struct _lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_DRAW_H*/
|
||||
1172
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_pos.c
Normal file
1172
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_pos.c
Normal file
File diff suppressed because it is too large
Load Diff
449
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_pos.h
Normal file
449
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_pos.h
Normal file
@@ -0,0 +1,449 @@
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* Transform a point using the angle and zoom style properties of an object
|
||||
* @param obj pointer to an object whose style properties should be used
|
||||
* @param p a point to transform, the result will be written back here too
|
||||
* @param recursive consider the transformation properties of the parents too
|
||||
* @param inv do the inverse of the transformation (-angle and 1/zoom)
|
||||
*/
|
||||
void lv_obj_transform_point(const struct _lv_obj_t * obj, lv_point_t * p, bool recursive, bool inv);
|
||||
|
||||
/**
|
||||
* Transform an area using the angle and zoom style properties of an object
|
||||
* @param obj pointer to an object whose style properties should be used
|
||||
* @param area an area to transform, the result will be written back here too
|
||||
* @param recursive consider the transformation properties of the parents too
|
||||
* @param inv do the inverse of the transformation (-angle and 1/zoom)
|
||||
*/
|
||||
void lv_obj_get_transformed_area(const struct _lv_obj_t * obj, lv_area_t * area, bool recursive, bool inv);
|
||||
|
||||
/**
|
||||
* 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*/
|
||||
800
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_scroll.c
Normal file
800
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_scroll.c
Normal file
@@ -0,0 +1,800 @@
|
||||
/**
|
||||
* @file lv_obj_scroll.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj_scroll.h"
|
||||
#include "lv_obj.h"
|
||||
#include "lv_indev.h"
|
||||
#include "lv_disp.h"
|
||||
#include "lv_indev_scroll.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
#define SCROLL_ANIM_TIME_MIN 200 /*ms*/
|
||||
#define SCROLL_ANIM_TIME_MAX 400 /*ms*/
|
||||
#define SCROLLBAR_MIN_SIZE (LV_DPX(10))
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void scroll_x_anim(void * obj, int32_t v);
|
||||
static void scroll_y_anim(void * obj, int32_t v);
|
||||
static void scroll_anim_ready_cb(lv_anim_t * a);
|
||||
static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_point_t * scroll_value,
|
||||
lv_anim_enable_t anim_en);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
void lv_obj_set_scrollbar_mode(lv_obj_t * obj, lv_scrollbar_mode_t mode)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
|
||||
if(obj->spec_attr->scrollbar_mode == mode) return;
|
||||
obj->spec_attr->scrollbar_mode = mode;
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
void lv_obj_set_scroll_dir(lv_obj_t * obj, lv_dir_t dir)
|
||||
{
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
|
||||
if(dir != obj->spec_attr->scroll_dir) {
|
||||
obj->spec_attr->scroll_dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_set_scroll_snap_x(lv_obj_t * obj, lv_scroll_snap_t align)
|
||||
{
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
obj->spec_attr->scroll_snap_x = align;
|
||||
}
|
||||
|
||||
void lv_obj_set_scroll_snap_y(lv_obj_t * obj, lv_scroll_snap_t align)
|
||||
{
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
obj->spec_attr->scroll_snap_y = align;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
lv_scrollbar_mode_t lv_obj_get_scrollbar_mode(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return obj->spec_attr->scrollbar_mode;
|
||||
else return LV_SCROLLBAR_MODE_AUTO;
|
||||
}
|
||||
|
||||
lv_dir_t lv_obj_get_scroll_dir(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return obj->spec_attr->scroll_dir;
|
||||
else return LV_DIR_ALL;
|
||||
}
|
||||
|
||||
lv_scroll_snap_t lv_obj_get_scroll_snap_x(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return obj->spec_attr->scroll_snap_x;
|
||||
else return LV_SCROLL_SNAP_NONE;
|
||||
}
|
||||
|
||||
lv_scroll_snap_t lv_obj_get_scroll_snap_y(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return obj->spec_attr->scroll_snap_y;
|
||||
else return LV_SCROLL_SNAP_NONE;
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_x(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.x;
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_y(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.y;
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_top(lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.y;
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_coord_t child_res = LV_COORD_MIN;
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
child_res = LV_MAX(child_res, child->coords.y2);
|
||||
}
|
||||
|
||||
lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN);
|
||||
lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN);
|
||||
|
||||
if(child_res != LV_COORD_MIN) {
|
||||
child_res -= (obj->coords.y2 - pad_bottom - border_width);
|
||||
}
|
||||
|
||||
lv_coord_t self_h = lv_obj_get_self_height(obj);
|
||||
self_h = self_h - (lv_obj_get_height(obj) - pad_top - pad_bottom - 2 * border_width);
|
||||
self_h -= lv_obj_get_scroll_y(obj);
|
||||
return LV_MAX(child_res, self_h);
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_left(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
/*Normally can't scroll the object out on the left.
|
||||
*So simply use the current scroll position as "left size"*/
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) {
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.x;
|
||||
}
|
||||
|
||||
/*With RTL base direction scrolling the left is normal so find the left most coordinate*/
|
||||
lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
|
||||
lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN);
|
||||
|
||||
lv_coord_t child_res = 0;
|
||||
|
||||
uint32_t i;
|
||||
lv_coord_t x1 = LV_COORD_MAX;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
x1 = LV_MIN(x1, child->coords.x1);
|
||||
|
||||
}
|
||||
|
||||
if(x1 != LV_COORD_MAX) {
|
||||
child_res = x1;
|
||||
child_res = (obj->coords.x1 + pad_left + border_width) - child_res;
|
||||
}
|
||||
else {
|
||||
child_res = LV_COORD_MIN;
|
||||
}
|
||||
|
||||
lv_coord_t self_w = lv_obj_get_self_width(obj);
|
||||
self_w = self_w - (lv_obj_get_width(obj) - pad_right - pad_left - 2 * border_width);
|
||||
self_w += lv_obj_get_scroll_x(obj);
|
||||
|
||||
return LV_MAX(child_res, self_w);
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
/*With RTL base dir can't scroll to the object out on the right.
|
||||
*So simply use the current scroll position as "right size"*/
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) {
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return obj->spec_attr->scroll.x;
|
||||
}
|
||||
|
||||
/*With other base direction (LTR) scrolling to the right is normal so find the right most coordinate*/
|
||||
lv_coord_t child_res = LV_COORD_MIN;
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
child_res = LV_MAX(child_res, child->coords.x2);
|
||||
}
|
||||
|
||||
lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
|
||||
lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN);
|
||||
|
||||
if(child_res != LV_COORD_MIN) {
|
||||
child_res -= (obj->coords.x2 - pad_right - border_width);
|
||||
}
|
||||
|
||||
lv_coord_t self_w;
|
||||
self_w = lv_obj_get_self_width(obj);
|
||||
self_w = self_w - (lv_obj_get_width(obj) - pad_right - pad_left - 2 * border_width);
|
||||
self_w -= lv_obj_get_scroll_x(obj);
|
||||
return LV_MAX(child_res, self_w);
|
||||
}
|
||||
|
||||
void lv_obj_get_scroll_end(struct _lv_obj_t * obj, lv_point_t * end)
|
||||
{
|
||||
lv_anim_t * a;
|
||||
a = lv_anim_get(obj, scroll_x_anim);
|
||||
end->x = a ? -a->end_value : lv_obj_get_scroll_x(obj);
|
||||
|
||||
a = lv_anim_get(obj, scroll_y_anim);
|
||||
end->y = a ? -a->end_value : lv_obj_get_scroll_y(obj);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
void lv_obj_scroll_by_bounded(lv_obj_t * obj, lv_coord_t dx, lv_coord_t dy, lv_anim_enable_t anim_en)
|
||||
{
|
||||
if(dx == 0 && dy == 0) return;
|
||||
|
||||
/*We need to know the final sizes for bound check*/
|
||||
lv_obj_update_layout(obj);
|
||||
|
||||
/*Don't let scroll more then naturally possible by the size of the content*/
|
||||
lv_coord_t x_current = -lv_obj_get_scroll_x(obj);
|
||||
lv_coord_t x_bounded = x_current + dx;
|
||||
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) {
|
||||
if(x_bounded > 0) x_bounded = 0;
|
||||
if(x_bounded < 0) {
|
||||
lv_coord_t scroll_max = lv_obj_get_scroll_left(obj) + lv_obj_get_scroll_right(obj);
|
||||
if(scroll_max < 0) scroll_max = 0;
|
||||
|
||||
if(x_bounded < -scroll_max) x_bounded = -scroll_max;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(x_bounded < 0) x_bounded = 0;
|
||||
if(x_bounded > 0) {
|
||||
lv_coord_t scroll_max = lv_obj_get_scroll_left(obj) + lv_obj_get_scroll_right(obj);
|
||||
if(scroll_max < 0) scroll_max = 0;
|
||||
|
||||
if(x_bounded > scroll_max) x_bounded = scroll_max;
|
||||
}
|
||||
}
|
||||
|
||||
/*Don't let scroll more then naturally possible by the size of the content*/
|
||||
lv_coord_t y_current = -lv_obj_get_scroll_y(obj);
|
||||
lv_coord_t y_bounded = y_current + dy;
|
||||
|
||||
if(y_bounded > 0) y_bounded = 0;
|
||||
if(y_bounded < 0) {
|
||||
lv_coord_t scroll_max = lv_obj_get_scroll_top(obj) + lv_obj_get_scroll_bottom(obj);
|
||||
if(scroll_max < 0) scroll_max = 0;
|
||||
if(y_bounded < -scroll_max) y_bounded = -scroll_max;
|
||||
}
|
||||
|
||||
dx = x_bounded - x_current;
|
||||
dy = y_bounded - y_current;
|
||||
if(dx || dy) {
|
||||
lv_obj_scroll_by(obj, dx, dy, anim_en);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t dx, lv_coord_t dy, lv_anim_enable_t anim_en)
|
||||
{
|
||||
if(dx == 0 && dy == 0) return;
|
||||
if(anim_en == LV_ANIM_ON) {
|
||||
lv_disp_t * d = lv_obj_get_disp(obj);
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, obj);
|
||||
lv_anim_set_ready_cb(&a, scroll_anim_ready_cb);
|
||||
|
||||
if(dx) {
|
||||
uint32_t t = lv_anim_speed_to_time((lv_disp_get_hor_res(d) * 2) >> 2, 0, dx);
|
||||
if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN;
|
||||
if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX;
|
||||
lv_anim_set_time(&a, t);
|
||||
lv_coord_t sx = lv_obj_get_scroll_x(obj);
|
||||
lv_anim_set_values(&a, -sx, -sx + dx);
|
||||
lv_anim_set_exec_cb(&a, scroll_x_anim);
|
||||
lv_anim_set_path_cb(&a, lv_anim_path_ease_out);
|
||||
|
||||
lv_res_t res;
|
||||
res = lv_event_send(obj, LV_EVENT_SCROLL_BEGIN, &a);
|
||||
if(res != LV_RES_OK) return;
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
if(dy) {
|
||||
uint32_t t = lv_anim_speed_to_time((lv_disp_get_ver_res(d) * 2) >> 2, 0, dy);
|
||||
if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN;
|
||||
if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX;
|
||||
lv_anim_set_time(&a, t);
|
||||
lv_coord_t sy = lv_obj_get_scroll_y(obj);
|
||||
lv_anim_set_values(&a, -sy, -sy + dy);
|
||||
lv_anim_set_exec_cb(&a, scroll_y_anim);
|
||||
lv_anim_set_path_cb(&a, lv_anim_path_ease_out);
|
||||
|
||||
lv_res_t res;
|
||||
res = lv_event_send(obj, LV_EVENT_SCROLL_BEGIN, &a);
|
||||
if(res != LV_RES_OK) return;
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*Remove pending animations*/
|
||||
lv_anim_del(obj, scroll_y_anim);
|
||||
lv_anim_del(obj, scroll_x_anim);
|
||||
|
||||
lv_res_t res;
|
||||
res = lv_event_send(obj, LV_EVENT_SCROLL_BEGIN, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
|
||||
res = _lv_obj_scroll_by_raw(obj, dx, dy);
|
||||
if(res != LV_RES_OK) return;
|
||||
|
||||
res = lv_event_send(obj, LV_EVENT_SCROLL_END, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_obj_scroll_to_x(obj, x, anim_en);
|
||||
lv_obj_scroll_to_y(obj, y, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to_x(lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_anim_del(obj, scroll_x_anim);
|
||||
|
||||
lv_coord_t scroll_x = lv_obj_get_scroll_x(obj);
|
||||
lv_coord_t diff = -x + scroll_x;
|
||||
|
||||
lv_obj_scroll_by_bounded(obj, diff, 0, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to_y(lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_anim_del(obj, scroll_y_anim);
|
||||
|
||||
lv_coord_t scroll_y = lv_obj_get_scroll_y(obj);
|
||||
lv_coord_t diff = -y + scroll_y;
|
||||
|
||||
lv_obj_scroll_by_bounded(obj, 0, diff, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to_view(lv_obj_t * obj, lv_anim_enable_t anim_en)
|
||||
{
|
||||
/*Be sure the screens layout is correct*/
|
||||
lv_obj_update_layout(obj);
|
||||
|
||||
lv_point_t p = {0, 0};
|
||||
scroll_area_into_view(&obj->coords, obj, &p, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to_view_recursive(lv_obj_t * obj, lv_anim_enable_t anim_en)
|
||||
{
|
||||
/*Be sure the screens layout is correct*/
|
||||
lv_obj_update_layout(obj);
|
||||
|
||||
lv_point_t p = {0, 0};
|
||||
lv_obj_t * child = obj;
|
||||
lv_obj_t * parent = lv_obj_get_parent(child);
|
||||
while(parent) {
|
||||
scroll_area_into_view(&obj->coords, child, &p, anim_en);
|
||||
child = parent;
|
||||
parent = lv_obj_get_parent(parent);
|
||||
}
|
||||
}
|
||||
|
||||
lv_res_t _lv_obj_scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
if(x == 0 && y == 0) return LV_RES_OK;
|
||||
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
|
||||
obj->spec_attr->scroll.x += x;
|
||||
obj->spec_attr->scroll.y += y;
|
||||
|
||||
lv_obj_move_children_by(obj, x, y, true);
|
||||
lv_res_t res = lv_event_send(obj, LV_EVENT_SCROLL, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
lv_obj_invalidate(obj);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
bool lv_obj_is_scrolling(const lv_obj_t * obj)
|
||||
{
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
while(indev) {
|
||||
if(lv_indev_get_scroll_obj(indev) == obj) return true;
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void lv_obj_update_snap(lv_obj_t * obj, lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_obj_update_layout(obj);
|
||||
lv_point_t p;
|
||||
lv_indev_scroll_get_snap_dist(obj, &p);
|
||||
lv_obj_scroll_by(obj, p.x, p.y, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * ver_area)
|
||||
{
|
||||
lv_area_set(hor_area, 0, 0, -1, -1);
|
||||
lv_area_set(ver_area, 0, 0, -1, -1);
|
||||
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLLABLE) == false) return;
|
||||
|
||||
lv_dir_t sm = lv_obj_get_scrollbar_mode(obj);
|
||||
if(sm == LV_SCROLLBAR_MODE_OFF) return;
|
||||
|
||||
/*If there is no indev scrolling this object but `mode==active` return*/
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
if(sm == LV_SCROLLBAR_MODE_ACTIVE) {
|
||||
while(indev) {
|
||||
if(lv_indev_get_scroll_obj(indev) == obj) break;
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
if(indev == NULL) return;
|
||||
}
|
||||
|
||||
lv_coord_t st = lv_obj_get_scroll_top(obj);
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(obj);
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(obj);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(obj);
|
||||
|
||||
lv_dir_t dir = lv_obj_get_scroll_dir(obj);
|
||||
|
||||
bool ver_draw = false;
|
||||
if((dir & LV_DIR_VER) &&
|
||||
((sm == LV_SCROLLBAR_MODE_ON) ||
|
||||
(sm == LV_SCROLLBAR_MODE_AUTO && (st > 0 || sb > 0)) ||
|
||||
(sm == LV_SCROLLBAR_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_DIR_VER))) {
|
||||
ver_draw = true;
|
||||
}
|
||||
|
||||
|
||||
bool hor_draw = false;
|
||||
if((dir & LV_DIR_HOR) &&
|
||||
((sm == LV_SCROLLBAR_MODE_ON) ||
|
||||
(sm == LV_SCROLLBAR_MODE_AUTO && (sl > 0 || sr > 0)) ||
|
||||
(sm == LV_SCROLLBAR_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_DIR_HOR))) {
|
||||
hor_draw = true;
|
||||
}
|
||||
|
||||
if(!hor_draw && !ver_draw) return;
|
||||
|
||||
bool rtl = lv_obj_get_style_base_dir(obj, LV_PART_SCROLLBAR) == LV_BASE_DIR_RTL ? true : false;
|
||||
|
||||
lv_coord_t top_space = lv_obj_get_style_pad_top(obj, LV_PART_SCROLLBAR);
|
||||
lv_coord_t bottom_space = lv_obj_get_style_pad_bottom(obj, LV_PART_SCROLLBAR);
|
||||
lv_coord_t left_space = lv_obj_get_style_pad_left(obj, LV_PART_SCROLLBAR);
|
||||
lv_coord_t right_space = lv_obj_get_style_pad_right(obj, LV_PART_SCROLLBAR);
|
||||
lv_coord_t tickness = lv_obj_get_style_width(obj, LV_PART_SCROLLBAR);
|
||||
|
||||
lv_coord_t obj_h = lv_obj_get_height(obj);
|
||||
lv_coord_t obj_w = lv_obj_get_width(obj);
|
||||
|
||||
/*Space required for the vertical and horizontal scrollbars*/
|
||||
lv_coord_t ver_reg_space = ver_draw ? tickness : 0;
|
||||
lv_coord_t hor_req_space = hor_draw ? tickness : 0;
|
||||
lv_coord_t rem;
|
||||
|
||||
if(lv_obj_get_style_bg_opa(obj, LV_PART_SCROLLBAR) < LV_OPA_MIN &&
|
||||
lv_obj_get_style_border_opa(obj, LV_PART_SCROLLBAR) < LV_OPA_MIN) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*Draw vertical scrollbar if the mode is ON or can be scrolled in this direction*/
|
||||
lv_coord_t content_h = obj_h + st + sb;
|
||||
if(ver_draw && content_h) {
|
||||
ver_area->y1 = obj->coords.y1;
|
||||
ver_area->y2 = obj->coords.y2;
|
||||
if(rtl) {
|
||||
ver_area->x1 = obj->coords.x1 + left_space;
|
||||
ver_area->x2 = ver_area->x1 + tickness - 1;
|
||||
}
|
||||
else {
|
||||
ver_area->x2 = obj->coords.x2 - right_space;
|
||||
ver_area->x1 = ver_area->x2 - tickness + 1;
|
||||
}
|
||||
|
||||
lv_coord_t sb_h = ((obj_h - top_space - bottom_space - hor_req_space) * obj_h) / content_h;
|
||||
sb_h = LV_MAX(sb_h, SCROLLBAR_MIN_SIZE);
|
||||
rem = (obj_h - top_space - bottom_space - hor_req_space) -
|
||||
sb_h; /*Remaining size from the scrollbar track that is not the scrollbar itself*/
|
||||
lv_coord_t scroll_h = content_h - obj_h; /*The size of the content which can be really scrolled*/
|
||||
if(scroll_h <= 0) {
|
||||
ver_area->y1 = obj->coords.y1 + top_space;
|
||||
ver_area->y2 = obj->coords.y2 - bottom_space - hor_req_space - 1;
|
||||
}
|
||||
else {
|
||||
lv_coord_t sb_y = (rem * sb) / scroll_h;
|
||||
sb_y = rem - sb_y;
|
||||
|
||||
ver_area->y1 = obj->coords.y1 + sb_y + top_space;
|
||||
ver_area->y2 = ver_area->y1 + sb_h - 1;
|
||||
if(ver_area->y1 < obj->coords.y1 + top_space) {
|
||||
ver_area->y1 = obj->coords.y1 + top_space;
|
||||
if(ver_area->y1 + SCROLLBAR_MIN_SIZE > ver_area->y2) {
|
||||
ver_area->y2 = ver_area->y1 + SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
if(ver_area->y2 > obj->coords.y2 - hor_req_space - bottom_space) {
|
||||
ver_area->y2 = obj->coords.y2 - hor_req_space - bottom_space;
|
||||
if(ver_area->y2 - SCROLLBAR_MIN_SIZE < ver_area->y1) {
|
||||
ver_area->y1 = ver_area->y2 - SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*Draw horizontal scrollbar if the mode is ON or can be scrolled in this direction*/
|
||||
lv_coord_t content_w = obj_w + sl + sr;
|
||||
if(hor_draw && content_w) {
|
||||
hor_area->y2 = obj->coords.y2 - bottom_space;
|
||||
hor_area->y1 = hor_area->y2 - tickness + 1;
|
||||
hor_area->x1 = obj->coords.x1;
|
||||
hor_area->x2 = obj->coords.x2;
|
||||
|
||||
lv_coord_t sb_w = ((obj_w - left_space - right_space - ver_reg_space) * obj_w) / content_w;
|
||||
sb_w = LV_MAX(sb_w, SCROLLBAR_MIN_SIZE);
|
||||
rem = (obj_w - left_space - right_space - ver_reg_space) -
|
||||
sb_w; /*Remaining size from the scrollbar track that is not the scrollbar itself*/
|
||||
lv_coord_t scroll_w = content_w - obj_w; /*The size of the content which can be really scrolled*/
|
||||
if(scroll_w <= 0) {
|
||||
if(rtl) {
|
||||
hor_area->x1 = obj->coords.x1 + left_space + ver_reg_space - 1;
|
||||
hor_area->x2 = obj->coords.x2 - right_space;
|
||||
}
|
||||
else {
|
||||
hor_area->x1 = obj->coords.x1 + left_space;
|
||||
hor_area->x2 = obj->coords.x2 - right_space - ver_reg_space - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_coord_t sb_x = (rem * sr) / scroll_w;
|
||||
sb_x = rem - sb_x;
|
||||
|
||||
if(rtl) {
|
||||
hor_area->x1 = obj->coords.x1 + sb_x + left_space + ver_reg_space;
|
||||
hor_area->x2 = hor_area->x1 + sb_w - 1;
|
||||
if(hor_area->x1 < obj->coords.x1 + left_space + ver_reg_space) {
|
||||
hor_area->x1 = obj->coords.x1 + left_space + ver_reg_space;
|
||||
if(hor_area->x1 + SCROLLBAR_MIN_SIZE > hor_area->x2) {
|
||||
hor_area->x2 = hor_area->x1 + SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
if(hor_area->x2 > obj->coords.x2 - right_space) {
|
||||
hor_area->x2 = obj->coords.x2 - right_space;
|
||||
if(hor_area->x2 - SCROLLBAR_MIN_SIZE < hor_area->x1) {
|
||||
hor_area->x1 = hor_area->x2 - SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
hor_area->x1 = obj->coords.x1 + sb_x + left_space;
|
||||
hor_area->x2 = hor_area->x1 + sb_w - 1;
|
||||
if(hor_area->x1 < obj->coords.x1 + left_space) {
|
||||
hor_area->x1 = obj->coords.x1 + left_space;
|
||||
if(hor_area->x1 + SCROLLBAR_MIN_SIZE > hor_area->x2) {
|
||||
hor_area->x2 = hor_area->x1 + SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
if(hor_area->x2 > obj->coords.x2 - ver_reg_space - right_space) {
|
||||
hor_area->x2 = obj->coords.x2 - ver_reg_space - right_space;
|
||||
if(hor_area->x2 - SCROLLBAR_MIN_SIZE < hor_area->x1) {
|
||||
hor_area->x1 = hor_area->x2 - SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_scrollbar_invalidate(lv_obj_t * obj)
|
||||
{
|
||||
lv_area_t hor_area;
|
||||
lv_area_t ver_area;
|
||||
lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area);
|
||||
|
||||
if(lv_area_get_size(&hor_area) <= 0 && lv_area_get_size(&ver_area) <= 0) return;
|
||||
|
||||
if(lv_area_get_size(&hor_area) > 0) lv_obj_invalidate_area(obj, &hor_area);
|
||||
if(lv_area_get_size(&ver_area) > 0) lv_obj_invalidate_area(obj, &ver_area);
|
||||
}
|
||||
|
||||
void lv_obj_readjust_scroll(lv_obj_t * obj, lv_anim_enable_t anim_en)
|
||||
{
|
||||
/*Be sure the bottom side is not remains scrolled in*/
|
||||
/*With snapping the content can't be scrolled in*/
|
||||
if(lv_obj_get_scroll_snap_y(obj) == LV_SCROLL_SNAP_NONE) {
|
||||
lv_coord_t st = lv_obj_get_scroll_top(obj);
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(obj);
|
||||
if(sb < 0 && st > 0) {
|
||||
sb = LV_MIN(st, -sb);
|
||||
lv_obj_scroll_by(obj, 0, sb, anim_en);
|
||||
}
|
||||
}
|
||||
|
||||
if(lv_obj_get_scroll_snap_x(obj) == LV_SCROLL_SNAP_NONE) {
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(obj);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(obj);
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) {
|
||||
/*Be sure the left side is not remains scrolled in*/
|
||||
if(sr < 0 && sl > 0) {
|
||||
sr = LV_MIN(sl, -sr);
|
||||
lv_obj_scroll_by(obj, sr, 0, anim_en);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*Be sure the right side is not remains scrolled in*/
|
||||
if(sl < 0 && sr > 0) {
|
||||
sr = LV_MIN(sr, -sl);
|
||||
lv_obj_scroll_by(obj, sl, 0, anim_en);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
static void scroll_x_anim(void * obj, int32_t v)
|
||||
{
|
||||
_lv_obj_scroll_by_raw(obj, v + lv_obj_get_scroll_x(obj), 0);
|
||||
}
|
||||
|
||||
static void scroll_y_anim(void * obj, int32_t v)
|
||||
{
|
||||
_lv_obj_scroll_by_raw(obj, 0, v + lv_obj_get_scroll_y(obj));
|
||||
}
|
||||
|
||||
static void scroll_anim_ready_cb(lv_anim_t * a)
|
||||
{
|
||||
lv_event_send(a->var, LV_EVENT_SCROLL_END, NULL);
|
||||
}
|
||||
|
||||
static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_point_t * scroll_value,
|
||||
lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_obj_t * parent = lv_obj_get_parent(child);
|
||||
if(!lv_obj_has_flag(parent, LV_OBJ_FLAG_SCROLLABLE)) return;
|
||||
|
||||
lv_dir_t scroll_dir = lv_obj_get_scroll_dir(parent);
|
||||
lv_coord_t snap_goal = 0;
|
||||
lv_coord_t act = 0;
|
||||
const lv_area_t * area_tmp;
|
||||
|
||||
lv_coord_t y_scroll = 0;
|
||||
lv_scroll_snap_t snap_y = lv_obj_get_scroll_snap_y(parent);
|
||||
if(snap_y != LV_SCROLL_SNAP_NONE) area_tmp = &child->coords;
|
||||
else area_tmp = area;
|
||||
|
||||
lv_coord_t border_width = lv_obj_get_style_border_width(parent, LV_PART_MAIN);
|
||||
lv_coord_t ptop = lv_obj_get_style_pad_top(parent, LV_PART_MAIN) + border_width;
|
||||
lv_coord_t pbottom = lv_obj_get_style_pad_bottom(parent, LV_PART_MAIN) + border_width;
|
||||
lv_coord_t top_diff = parent->coords.y1 + ptop - area_tmp->y1 - scroll_value->y;
|
||||
lv_coord_t bottom_diff = -(parent->coords.y2 - pbottom - area_tmp->y2 - scroll_value->y);
|
||||
lv_coord_t parent_h = lv_obj_get_height(parent) - ptop - pbottom;
|
||||
if((top_diff >= 0 && bottom_diff >= 0)) y_scroll = 0;
|
||||
else if(top_diff > 0) {
|
||||
y_scroll = top_diff;
|
||||
/*Do not let scrolling in*/
|
||||
lv_coord_t st = lv_obj_get_scroll_top(parent);
|
||||
if(st - y_scroll < 0) y_scroll = 0;
|
||||
}
|
||||
else if(bottom_diff > 0) {
|
||||
y_scroll = -bottom_diff;
|
||||
/*Do not let scrolling in*/
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(parent);
|
||||
if(sb + y_scroll < 0) y_scroll = 0;
|
||||
}
|
||||
|
||||
switch(snap_y) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
snap_goal = parent->coords.y1 + ptop;
|
||||
act = area_tmp->y1 + y_scroll;
|
||||
y_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
snap_goal = parent->coords.y2 - pbottom;
|
||||
act = area_tmp->y2 + y_scroll;
|
||||
y_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
snap_goal = parent->coords.y1 + ptop + parent_h / 2;
|
||||
act = lv_area_get_height(area_tmp) / 2 + area_tmp->y1 + y_scroll;
|
||||
y_scroll += snap_goal - act;
|
||||
break;
|
||||
}
|
||||
|
||||
lv_coord_t x_scroll = 0;
|
||||
lv_scroll_snap_t snap_x = lv_obj_get_scroll_snap_x(parent);
|
||||
if(snap_x != LV_SCROLL_SNAP_NONE) area_tmp = &child->coords;
|
||||
else area_tmp = area;
|
||||
|
||||
lv_coord_t pleft = lv_obj_get_style_pad_left(parent, LV_PART_MAIN) + border_width;
|
||||
lv_coord_t pright = lv_obj_get_style_pad_right(parent, LV_PART_MAIN) + border_width;
|
||||
lv_coord_t left_diff = parent->coords.x1 + pleft - area_tmp->x1 - scroll_value->x;
|
||||
lv_coord_t right_diff = -(parent->coords.x2 - pright - area_tmp->x2 - scroll_value->x);
|
||||
if((left_diff >= 0 && right_diff >= 0)) x_scroll = 0;
|
||||
else if(left_diff > 0) {
|
||||
x_scroll = left_diff;
|
||||
/*Do not let scrolling in*/
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(parent);
|
||||
if(sl - x_scroll < 0) x_scroll = 0;
|
||||
}
|
||||
else if(right_diff > 0) {
|
||||
x_scroll = -right_diff;
|
||||
/*Do not let scrolling in*/
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(parent);
|
||||
if(sr + x_scroll < 0) x_scroll = 0;
|
||||
}
|
||||
|
||||
lv_coord_t parent_w = lv_obj_get_width(parent) - pleft - pright;
|
||||
switch(snap_x) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
snap_goal = parent->coords.x1 + pleft;
|
||||
act = area_tmp->x1 + x_scroll;
|
||||
x_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
snap_goal = parent->coords.x2 - pright;
|
||||
act = area_tmp->x2 + x_scroll;
|
||||
x_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
snap_goal = parent->coords.x1 + pleft + parent_w / 2;
|
||||
act = lv_area_get_width(area_tmp) / 2 + area_tmp->x1 + x_scroll;
|
||||
x_scroll += snap_goal - act;
|
||||
break;
|
||||
}
|
||||
|
||||
/*Remove any pending scroll animations.*/
|
||||
bool y_del = lv_anim_del(parent, scroll_y_anim);
|
||||
bool x_del = lv_anim_del(parent, scroll_x_anim);
|
||||
if(y_del || x_del) {
|
||||
lv_res_t res;
|
||||
res = lv_event_send(parent, LV_EVENT_SCROLL_END, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
}
|
||||
|
||||
if((scroll_dir & LV_DIR_LEFT) == 0 && x_scroll < 0) x_scroll = 0;
|
||||
if((scroll_dir & LV_DIR_RIGHT) == 0 && x_scroll > 0) x_scroll = 0;
|
||||
if((scroll_dir & LV_DIR_TOP) == 0 && y_scroll < 0) y_scroll = 0;
|
||||
if((scroll_dir & LV_DIR_BOTTOM) == 0 && y_scroll > 0) y_scroll = 0;
|
||||
|
||||
scroll_value->x += anim_en == LV_ANIM_OFF ? 0 : x_scroll;
|
||||
scroll_value->y += anim_en == LV_ANIM_OFF ? 0 : y_scroll;
|
||||
lv_obj_scroll_by(parent, x_scroll, y_scroll, anim_en);
|
||||
}
|
||||
307
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_scroll.h
Normal file
307
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_scroll.h
Normal file
@@ -0,0 +1,307 @@
|
||||
/**
|
||||
* @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"
|
||||
#include "../misc/lv_types.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);
|
||||
|
||||
|
||||
/**
|
||||
* Low level function to scroll by given x and y coordinates.
|
||||
* `LV_EVENT_SCROLL` is sent.
|
||||
* @param obj pointer to an object to scroll
|
||||
* @param x pixels to scroll horizontally
|
||||
* @param y pixels to scroll vertically
|
||||
* @return `LV_RES_INV`: to object was deleted in `LV_EVENT_SCROLL`;
|
||||
* `LV_RES_OK`: if the object is still valid
|
||||
*/
|
||||
lv_res_t _lv_obj_scroll_by_raw(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
/**
|
||||
* 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*/
|
||||
866
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_style.c
Normal file
866
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_style.c
Normal file
@@ -0,0 +1,866 @@
|
||||
/**
|
||||
* @file lv_obj_style.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "lv_disp.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_obj_t * obj;
|
||||
lv_style_prop_t prop;
|
||||
lv_style_selector_t selector;
|
||||
lv_style_value_t start_value;
|
||||
lv_style_value_t end_value;
|
||||
} trans_t;
|
||||
|
||||
typedef enum {
|
||||
CACHE_ZERO = 0,
|
||||
CACHE_TRUE = 1,
|
||||
CACHE_UNSET = 2,
|
||||
CACHE_255 = 3,
|
||||
CACHE_NEED_CHECK = 4,
|
||||
} cache_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_style_t * get_local_style(lv_obj_t * obj, lv_style_selector_t selector);
|
||||
static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, uint32_t part);
|
||||
static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v);
|
||||
static void report_style_change_core(void * style, lv_obj_t * obj);
|
||||
static void refresh_children_style(lv_obj_t * obj);
|
||||
static bool trans_del(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, trans_t * tr_limit);
|
||||
static void trans_anim_cb(void * _tr, int32_t v);
|
||||
static void trans_anim_start_cb(lv_anim_t * a);
|
||||
static void trans_anim_ready_cb(lv_anim_t * a);
|
||||
static lv_layer_type_t calculate_layer_type(lv_obj_t * obj);
|
||||
static void fade_anim_cb(void * obj, int32_t v);
|
||||
static void fade_in_anim_ready(lv_anim_t * a);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static bool style_refr = true;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void _lv_obj_style_init(void)
|
||||
{
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_obj_style_trans_ll), sizeof(trans_t));
|
||||
}
|
||||
|
||||
void lv_obj_add_style(lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector)
|
||||
{
|
||||
trans_del(obj, selector, LV_STYLE_PROP_ANY, NULL);
|
||||
|
||||
uint32_t i;
|
||||
/*Go after the transition and local styles*/
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans) continue;
|
||||
if(obj->styles[i].is_local) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
/*Now `i` is at the first normal style. Insert the new style before this*/
|
||||
|
||||
/*Allocate space for the new style and shift the rest of the style to the end*/
|
||||
obj->style_cnt++;
|
||||
obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t));
|
||||
|
||||
uint32_t j;
|
||||
for(j = obj->style_cnt - 1; j > i ; j--) {
|
||||
obj->styles[j] = obj->styles[j - 1];
|
||||
}
|
||||
|
||||
lv_memset_00(&obj->styles[i], sizeof(_lv_obj_style_t));
|
||||
obj->styles[i].style = style;
|
||||
obj->styles[i].selector = selector;
|
||||
|
||||
lv_obj_refresh_style(obj, selector, LV_STYLE_PROP_ANY);
|
||||
}
|
||||
|
||||
void lv_obj_remove_style(lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector)
|
||||
{
|
||||
lv_state_t state = lv_obj_style_get_selector_state(selector);
|
||||
lv_part_t part = lv_obj_style_get_selector_part(selector);
|
||||
lv_style_prop_t prop = LV_STYLE_PROP_ANY;
|
||||
if(style && style->prop_cnt == 0) prop = LV_STYLE_PROP_INV;
|
||||
|
||||
uint32_t i = 0;
|
||||
bool deleted = false;
|
||||
while(i < obj->style_cnt) {
|
||||
lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector);
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector);
|
||||
if((state != LV_STATE_ANY && state_act != state) ||
|
||||
(part != LV_PART_ANY && part_act != part) ||
|
||||
(style != NULL && style != obj->styles[i].style)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(obj->styles[i].is_trans) {
|
||||
trans_del(obj, part, LV_STYLE_PROP_ANY, NULL);
|
||||
}
|
||||
|
||||
if(obj->styles[i].is_local || obj->styles[i].is_trans) {
|
||||
lv_style_reset(obj->styles[i].style);
|
||||
lv_mem_free(obj->styles[i].style);
|
||||
obj->styles[i].style = NULL;
|
||||
}
|
||||
|
||||
/*Shift the styles after `i` by one*/
|
||||
uint32_t j;
|
||||
for(j = i; j < (uint32_t)obj->style_cnt - 1 ; j++) {
|
||||
obj->styles[j] = obj->styles[j + 1];
|
||||
}
|
||||
|
||||
obj->style_cnt--;
|
||||
obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t));
|
||||
|
||||
deleted = true;
|
||||
/*The style from the current `i` index is removed, so `i` points to the next style.
|
||||
*Therefore it doesn't needs to be incremented*/
|
||||
}
|
||||
if(deleted && prop != LV_STYLE_PROP_INV) {
|
||||
lv_obj_refresh_style(obj, part, prop);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_report_style_change(lv_style_t * style)
|
||||
{
|
||||
if(!style_refr) return;
|
||||
lv_disp_t * d = lv_disp_get_next(NULL);
|
||||
|
||||
while(d) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < d->screen_cnt; i++) {
|
||||
report_style_change_core(style, d->screens[i]);
|
||||
}
|
||||
d = lv_disp_get_next(d);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_refresh_style(lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(!style_refr) return;
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
lv_part_t part = lv_obj_style_get_selector_part(selector);
|
||||
|
||||
bool is_layout_refr = lv_style_prop_has_flag(prop, LV_STYLE_PROP_LAYOUT_REFR);
|
||||
bool is_ext_draw = lv_style_prop_has_flag(prop, LV_STYLE_PROP_EXT_DRAW);
|
||||
bool is_inheritable = lv_style_prop_has_flag(prop, LV_STYLE_PROP_INHERIT);
|
||||
bool is_layer_refr = lv_style_prop_has_flag(prop, LV_STYLE_PROP_LAYER_REFR);
|
||||
|
||||
if(is_layout_refr) {
|
||||
if(part == LV_PART_ANY ||
|
||||
part == LV_PART_MAIN ||
|
||||
lv_obj_get_style_height(obj, 0) == LV_SIZE_CONTENT ||
|
||||
lv_obj_get_style_width(obj, 0) == LV_SIZE_CONTENT) {
|
||||
lv_event_send(obj, LV_EVENT_STYLE_CHANGED, NULL);
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
}
|
||||
}
|
||||
if((part == LV_PART_ANY || part == LV_PART_MAIN) && (prop == LV_STYLE_PROP_ANY || is_layout_refr)) {
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
if(parent) lv_obj_mark_layout_as_dirty(parent);
|
||||
}
|
||||
|
||||
/*Cache the layer type*/
|
||||
if((part == LV_PART_ANY || part == LV_PART_MAIN) && is_layer_refr) {
|
||||
lv_layer_type_t layer_type = calculate_layer_type(obj);
|
||||
if(obj->spec_attr) obj->spec_attr->layer_type = layer_type;
|
||||
else if(layer_type != LV_LAYER_TYPE_NONE) {
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
obj->spec_attr->layer_type = layer_type;
|
||||
}
|
||||
}
|
||||
|
||||
if(prop == LV_STYLE_PROP_ANY || is_ext_draw) {
|
||||
lv_obj_refresh_ext_draw_size(obj);
|
||||
}
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
if(prop == LV_STYLE_PROP_ANY || (is_inheritable && (is_ext_draw || is_layout_refr))) {
|
||||
if(part != LV_PART_SCROLLBAR) {
|
||||
refresh_children_style(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_enable_style_refresh(bool en)
|
||||
{
|
||||
style_refr = en;
|
||||
}
|
||||
|
||||
lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop)
|
||||
{
|
||||
lv_style_value_t value_act;
|
||||
bool inheritable = lv_style_prop_has_flag(prop, LV_STYLE_PROP_INHERIT);
|
||||
lv_style_res_t found = LV_STYLE_RES_NOT_FOUND;
|
||||
while(obj) {
|
||||
found = get_prop_core(obj, part, prop, &value_act);
|
||||
if(found == LV_STYLE_RES_FOUND) break;
|
||||
if(!inheritable) break;
|
||||
|
||||
/*If not found, check the `MAIN` style first*/
|
||||
if(found != LV_STYLE_RES_INHERIT && part != LV_PART_MAIN) {
|
||||
part = LV_PART_MAIN;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*Check the parent too.*/
|
||||
obj = lv_obj_get_parent(obj);
|
||||
}
|
||||
|
||||
if(found != LV_STYLE_RES_FOUND) {
|
||||
if(part == LV_PART_MAIN && (prop == LV_STYLE_WIDTH || prop == LV_STYLE_HEIGHT)) {
|
||||
const lv_obj_class_t * cls = obj->class_p;
|
||||
while(cls) {
|
||||
if(prop == LV_STYLE_WIDTH) {
|
||||
if(cls->width_def != 0) break;
|
||||
}
|
||||
else {
|
||||
if(cls->height_def != 0) break;
|
||||
}
|
||||
cls = cls->base_class;
|
||||
}
|
||||
|
||||
if(cls) {
|
||||
value_act.num = prop == LV_STYLE_WIDTH ? cls->width_def : cls->height_def;
|
||||
}
|
||||
else {
|
||||
value_act.num = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
value_act = lv_style_prop_get_default(prop);
|
||||
}
|
||||
}
|
||||
return value_act;
|
||||
}
|
||||
|
||||
void lv_obj_set_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value,
|
||||
lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_t * style = get_local_style(obj, selector);
|
||||
lv_style_set_prop(style, prop, value);
|
||||
lv_obj_refresh_style(obj, selector, prop);
|
||||
}
|
||||
|
||||
void lv_obj_set_local_style_prop_meta(lv_obj_t * obj, lv_style_prop_t prop, uint16_t meta,
|
||||
lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_t * style = get_local_style(obj, selector);
|
||||
lv_style_set_prop_meta(style, prop, meta);
|
||||
lv_obj_refresh_style(obj, selector, prop);
|
||||
}
|
||||
|
||||
|
||||
lv_style_res_t lv_obj_get_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value,
|
||||
lv_style_selector_t selector)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_local &&
|
||||
obj->styles[i].selector == selector) {
|
||||
return lv_style_get_prop(obj->styles[i].style, prop, value);
|
||||
}
|
||||
}
|
||||
|
||||
return LV_STYLE_RES_NOT_FOUND;
|
||||
}
|
||||
|
||||
bool lv_obj_remove_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
uint32_t i;
|
||||
/*Find the style*/
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_local &&
|
||||
obj->styles[i].selector == selector) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*The style is not found*/
|
||||
if(i == obj->style_cnt) return false;
|
||||
|
||||
lv_res_t res = lv_style_remove_prop(obj->styles[i].style, prop);
|
||||
if(res == LV_RES_OK) {
|
||||
lv_obj_refresh_style(obj, selector, prop);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void _lv_obj_style_create_transition(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_dsc)
|
||||
{
|
||||
trans_t * tr;
|
||||
|
||||
/*Get the previous and current values*/
|
||||
obj->skip_trans = 1;
|
||||
obj->state = prev_state;
|
||||
lv_style_value_t v1 = lv_obj_get_style_prop(obj, part, tr_dsc->prop);
|
||||
obj->state = new_state;
|
||||
lv_style_value_t v2 = lv_obj_get_style_prop(obj, part, tr_dsc->prop);
|
||||
obj->skip_trans = 0;
|
||||
|
||||
if(v1.ptr == v2.ptr && v1.num == v2.num && v1.color.full == v2.color.full) return;
|
||||
obj->state = prev_state;
|
||||
v1 = lv_obj_get_style_prop(obj, part, tr_dsc->prop);
|
||||
obj->state = new_state;
|
||||
|
||||
_lv_obj_style_t * style_trans = get_trans_style(obj, part);
|
||||
lv_style_set_prop(style_trans->style, tr_dsc->prop, v1); /*Be sure `trans_style` has a valid value*/
|
||||
|
||||
if(tr_dsc->prop == LV_STYLE_RADIUS) {
|
||||
if(v1.num == LV_RADIUS_CIRCLE || v2.num == LV_RADIUS_CIRCLE) {
|
||||
lv_coord_t whalf = lv_obj_get_width(obj) / 2;
|
||||
lv_coord_t hhalf = lv_obj_get_height(obj) / 2;
|
||||
if(v1.num == LV_RADIUS_CIRCLE) v1.num = LV_MIN(whalf + 1, hhalf + 1);
|
||||
if(v2.num == LV_RADIUS_CIRCLE) v2.num = LV_MIN(whalf + 1, hhalf + 1);
|
||||
}
|
||||
}
|
||||
|
||||
tr = _lv_ll_ins_head(&LV_GC_ROOT(_lv_obj_style_trans_ll));
|
||||
LV_ASSERT_MALLOC(tr);
|
||||
if(tr == NULL) return;
|
||||
tr->start_value = v1;
|
||||
tr->end_value = v2;
|
||||
tr->obj = obj;
|
||||
tr->prop = tr_dsc->prop;
|
||||
tr->selector = part;
|
||||
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, tr);
|
||||
lv_anim_set_exec_cb(&a, trans_anim_cb);
|
||||
lv_anim_set_start_cb(&a, trans_anim_start_cb);
|
||||
lv_anim_set_ready_cb(&a, trans_anim_ready_cb);
|
||||
lv_anim_set_values(&a, 0x00, 0xFF);
|
||||
lv_anim_set_time(&a, tr_dsc->time);
|
||||
lv_anim_set_delay(&a, tr_dsc->delay);
|
||||
lv_anim_set_path_cb(&a, tr_dsc->path_cb);
|
||||
lv_anim_set_early_apply(&a, false);
|
||||
#if LV_USE_USER_DATA
|
||||
a.user_data = tr_dsc->user_data;
|
||||
#endif
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
|
||||
lv_style_value_t _lv_obj_style_apply_color_filter(const lv_obj_t * obj, uint32_t part, lv_style_value_t v)
|
||||
{
|
||||
if(obj == NULL) return v;
|
||||
const lv_color_filter_dsc_t * f = lv_obj_get_style_color_filter_dsc(obj, part);
|
||||
if(f && f->filter_cb) {
|
||||
lv_opa_t f_opa = lv_obj_get_style_color_filter_opa(obj, part);
|
||||
if(f_opa != 0) v.color = f->filter_cb(f, v.color, f_opa);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
_lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t state1, lv_state_t state2)
|
||||
{
|
||||
_lv_style_state_cmp_t res = _LV_STYLE_STATE_CMP_SAME;
|
||||
|
||||
/*Are there any new styles for the new state?*/
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans) continue;
|
||||
|
||||
lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector);
|
||||
/*The style is valid for a state but not the other*/
|
||||
bool valid1 = state_act & (~state1) ? false : true;
|
||||
bool valid2 = state_act & (~state2) ? false : true;
|
||||
if(valid1 != valid2) {
|
||||
lv_style_t * style = obj->styles[i].style;
|
||||
lv_style_value_t v;
|
||||
/*If there is layout difference on the main part, return immediately. There is no more serious difference*/
|
||||
bool layout_diff = false;
|
||||
if(lv_style_get_prop(style, LV_STYLE_PAD_TOP, &v))layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_BOTTOM, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_LEFT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_RIGHT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_COLUMN, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_ROW, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_LAYOUT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSLATE_X, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSLATE_Y, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_WIDTH, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_HEIGHT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_MIN_WIDTH, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_MAX_WIDTH, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_MIN_HEIGHT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_MAX_HEIGHT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_BORDER_WIDTH, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ANGLE, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ZOOM, &v)) layout_diff = true;
|
||||
|
||||
if(layout_diff) {
|
||||
return _LV_STYLE_STATE_CMP_DIFF_LAYOUT;
|
||||
}
|
||||
|
||||
/*Check for draw pad changes*/
|
||||
if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_HEIGHT, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ANGLE, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ZOOM, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_OUTLINE_OPA, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_OUTLINE_PAD, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_OUTLINE_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_OPA, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_OFS_X, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_OFS_Y, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_SPREAD, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_LINE_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(res == _LV_STYLE_STATE_CMP_SAME) res = _LV_STYLE_STATE_CMP_DIFF_REDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void lv_obj_fade_in(lv_obj_t * obj, uint32_t time, uint32_t delay)
|
||||
{
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, obj);
|
||||
lv_anim_set_values(&a, 0, LV_OPA_COVER);
|
||||
lv_anim_set_exec_cb(&a, fade_anim_cb);
|
||||
lv_anim_set_ready_cb(&a, fade_in_anim_ready);
|
||||
lv_anim_set_time(&a, time);
|
||||
lv_anim_set_delay(&a, delay);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
void lv_obj_fade_out(lv_obj_t * obj, uint32_t time, uint32_t delay)
|
||||
{
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, obj);
|
||||
lv_anim_set_values(&a, lv_obj_get_style_opa(obj, 0), LV_OPA_TRANSP);
|
||||
lv_anim_set_exec_cb(&a, fade_anim_cb);
|
||||
lv_anim_set_time(&a, time);
|
||||
lv_anim_set_delay(&a, delay);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
lv_state_t lv_obj_style_get_selector_state(lv_style_selector_t selector)
|
||||
{
|
||||
return selector & 0xFFFF;
|
||||
}
|
||||
|
||||
lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector)
|
||||
{
|
||||
return selector & 0xFF0000;
|
||||
}
|
||||
|
||||
|
||||
lv_text_align_t lv_obj_calculate_style_text_align(const struct _lv_obj_t * obj, lv_part_t part, const char * txt)
|
||||
{
|
||||
lv_text_align_t align = lv_obj_get_style_text_align(obj, part);
|
||||
lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, part);
|
||||
lv_bidi_calculate_align(&align, &base_dir, txt);
|
||||
return align;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get the local style of an object for a given part and for a given state.
|
||||
* If the local style for the part-state pair doesn't exist allocate and return it.
|
||||
* @param obj pointer to an object
|
||||
* @param selector OR-ed value of parts and state for which the style should be get
|
||||
* @return pointer to the local style
|
||||
*/
|
||||
static lv_style_t * get_local_style(lv_obj_t * obj, lv_style_selector_t selector)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_local &&
|
||||
obj->styles[i].selector == selector) {
|
||||
return obj->styles[i].style;
|
||||
}
|
||||
}
|
||||
|
||||
obj->style_cnt++;
|
||||
obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t));
|
||||
LV_ASSERT_MALLOC(obj->styles);
|
||||
|
||||
for(i = obj->style_cnt - 1; i > 0 ; i--) {
|
||||
/*Copy only normal styles (not local and transition).
|
||||
*The new local style will be added as the last local style*/
|
||||
if(obj->styles[i - 1].is_local || obj->styles[i - 1].is_trans) break;
|
||||
obj->styles[i] = obj->styles[i - 1];
|
||||
}
|
||||
|
||||
lv_memset_00(&obj->styles[i], sizeof(_lv_obj_style_t));
|
||||
obj->styles[i].style = lv_mem_alloc(sizeof(lv_style_t));
|
||||
lv_style_init(obj->styles[i].style);
|
||||
obj->styles[i].is_local = 1;
|
||||
obj->styles[i].selector = selector;
|
||||
return obj->styles[i].style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the transition style of an object for a given part and for a given state.
|
||||
* If the transition style for the part-state pair doesn't exist allocate and return it.
|
||||
* @param obj pointer to an object
|
||||
* @param selector OR-ed value of parts and state for which the style should be get
|
||||
* @return pointer to the transition style
|
||||
*/
|
||||
static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, lv_style_selector_t selector)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans && obj->styles[i].selector == selector) break;
|
||||
}
|
||||
|
||||
/*Already have a transition style for it*/
|
||||
if(i != obj->style_cnt) return &obj->styles[i];
|
||||
|
||||
obj->style_cnt++;
|
||||
obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t));
|
||||
|
||||
for(i = obj->style_cnt - 1; i > 0 ; i--) {
|
||||
obj->styles[i] = obj->styles[i - 1];
|
||||
}
|
||||
|
||||
lv_memset_00(&obj->styles[0], sizeof(_lv_obj_style_t));
|
||||
obj->styles[0].style = lv_mem_alloc(sizeof(lv_style_t));
|
||||
lv_style_init(obj->styles[0].style);
|
||||
obj->styles[0].is_trans = 1;
|
||||
obj->styles[0].selector = selector;
|
||||
return &obj->styles[0];
|
||||
}
|
||||
|
||||
|
||||
static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v)
|
||||
{
|
||||
uint8_t group = 1 << _lv_style_get_prop_group(prop);
|
||||
int32_t weight = -1;
|
||||
lv_state_t state = obj->state;
|
||||
lv_state_t state_inv = ~state;
|
||||
lv_style_value_t value_tmp;
|
||||
bool skip_trans = obj->skip_trans;
|
||||
uint32_t i;
|
||||
lv_style_res_t found;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
_lv_obj_style_t * obj_style = &obj->styles[i];
|
||||
if(obj_style->is_trans == false) break;
|
||||
if(skip_trans) continue;
|
||||
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector);
|
||||
|
||||
if(part_act != part) continue;
|
||||
if((obj_style->style->has_group & group) == 0) continue;
|
||||
found = lv_style_get_prop(obj_style->style, prop, &value_tmp);
|
||||
if(found == LV_STYLE_RES_FOUND) {
|
||||
*v = value_tmp;
|
||||
return LV_STYLE_RES_FOUND;
|
||||
}
|
||||
else if(found == LV_STYLE_RES_INHERIT) {
|
||||
return LV_STYLE_RES_INHERIT;
|
||||
}
|
||||
}
|
||||
|
||||
for(; i < obj->style_cnt; i++) {
|
||||
if((obj->styles[i].style->has_group & group) == 0) continue;
|
||||
_lv_obj_style_t * obj_style = &obj->styles[i];
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector);
|
||||
lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector);
|
||||
if(part_act != part) continue;
|
||||
|
||||
/*Be sure the style not specifies other state than the requested.
|
||||
*E.g. For HOVER+PRESS object state, HOVER style only is OK, but HOVER+FOCUS style is not*/
|
||||
if((state_act & state_inv)) continue;
|
||||
|
||||
/*Check only better candidates*/
|
||||
if(state_act <= weight) continue;
|
||||
|
||||
found = lv_style_get_prop(obj_style->style, prop, &value_tmp);
|
||||
|
||||
if(found == LV_STYLE_RES_FOUND) {
|
||||
if(state_act == state) {
|
||||
*v = value_tmp;
|
||||
return LV_STYLE_RES_FOUND;
|
||||
}
|
||||
if(weight < state_act) {
|
||||
weight = state_act;
|
||||
*v = value_tmp;
|
||||
}
|
||||
}
|
||||
else if(found == LV_STYLE_RES_INHERIT) {
|
||||
return LV_STYLE_RES_INHERIT;
|
||||
}
|
||||
}
|
||||
|
||||
if(weight >= 0) {
|
||||
*v = value_tmp;
|
||||
return LV_STYLE_RES_FOUND;
|
||||
}
|
||||
else return LV_STYLE_RES_NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the style of all children of an object. (Called recursively)
|
||||
* @param style refresh objects only with this
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
static void report_style_change_core(void * style, lv_obj_t * obj)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(style == NULL || obj->styles[i].style == style) {
|
||||
lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
report_style_change_core(style, obj->spec_attr->children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively refresh the style of the children. Go deeper until a not NULL style is found
|
||||
* because the NULL styles are inherited from the parent
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
static void refresh_children_style(lv_obj_t * obj)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
lv_obj_invalidate(child);
|
||||
lv_event_send(child, LV_EVENT_STYLE_CHANGED, NULL);
|
||||
lv_obj_invalidate(child);
|
||||
|
||||
refresh_children_style(child); /*Check children too*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the transition from object's part's property.
|
||||
* - Remove the transition from `_lv_obj_style_trans_ll` and free it
|
||||
* - Delete pending transitions
|
||||
* @param obj pointer to an object which transition(s) should be removed
|
||||
* @param part a part of object or 0xFF to remove from all parts
|
||||
* @param prop a property or 0xFF to remove all properties
|
||||
* @param tr_limit delete transitions only "older" than this. `NULL` if not used
|
||||
*/
|
||||
static bool trans_del(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, trans_t * tr_limit)
|
||||
{
|
||||
trans_t * tr;
|
||||
trans_t * tr_prev;
|
||||
bool removed = false;
|
||||
tr = _lv_ll_get_tail(&LV_GC_ROOT(_lv_obj_style_trans_ll));
|
||||
while(tr != NULL) {
|
||||
if(tr == tr_limit) break;
|
||||
|
||||
/*'tr' might be deleted, so get the next object while 'tr' is valid*/
|
||||
tr_prev = _lv_ll_get_prev(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr);
|
||||
|
||||
if(tr->obj == obj && (part == tr->selector || part == LV_PART_ANY) && (prop == tr->prop || prop == LV_STYLE_PROP_ANY)) {
|
||||
/*Remove any transitioned properties from the trans. style
|
||||
*to allow changing it by normal styles*/
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans && (part == LV_PART_ANY || obj->styles[i].selector == part)) {
|
||||
lv_style_remove_prop(obj->styles[i].style, tr->prop);
|
||||
}
|
||||
}
|
||||
|
||||
/*Free the transition descriptor too*/
|
||||
lv_anim_del(tr, NULL);
|
||||
_lv_ll_remove(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr);
|
||||
lv_mem_free(tr);
|
||||
removed = true;
|
||||
|
||||
}
|
||||
tr = tr_prev;
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
static void trans_anim_cb(void * _tr, int32_t v)
|
||||
{
|
||||
trans_t * tr = _tr;
|
||||
lv_obj_t * obj = tr->obj;
|
||||
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans == 0 || obj->styles[i].selector != tr->selector) continue;
|
||||
|
||||
lv_style_value_t value_final;
|
||||
switch(tr->prop) {
|
||||
|
||||
case LV_STYLE_BORDER_SIDE:
|
||||
case LV_STYLE_BORDER_POST:
|
||||
case LV_STYLE_BLEND_MODE:
|
||||
if(v < 255) value_final.num = tr->start_value.num;
|
||||
else value_final.num = tr->end_value.num;
|
||||
break;
|
||||
case LV_STYLE_TRANSITION:
|
||||
case LV_STYLE_TEXT_FONT:
|
||||
if(v < 255) value_final.ptr = tr->start_value.ptr;
|
||||
else value_final.ptr = tr->end_value.ptr;
|
||||
break;
|
||||
case LV_STYLE_COLOR_FILTER_DSC:
|
||||
if(tr->start_value.ptr == NULL) value_final.ptr = tr->end_value.ptr;
|
||||
else if(tr->end_value.ptr == NULL) value_final.ptr = tr->start_value.ptr;
|
||||
else if(v < 128) value_final.ptr = tr->start_value.ptr;
|
||||
else value_final.ptr = tr->end_value.ptr;
|
||||
break;
|
||||
case LV_STYLE_BG_COLOR:
|
||||
case LV_STYLE_BORDER_COLOR:
|
||||
case LV_STYLE_TEXT_COLOR:
|
||||
case LV_STYLE_SHADOW_COLOR:
|
||||
case LV_STYLE_OUTLINE_COLOR:
|
||||
case LV_STYLE_IMG_RECOLOR:
|
||||
if(v <= 0) value_final.color = tr->start_value.color;
|
||||
else if(v >= 255) value_final.color = tr->end_value.color;
|
||||
else value_final.color = lv_color_mix(tr->end_value.color, tr->start_value.color, v);
|
||||
break;
|
||||
|
||||
default:
|
||||
if(v == 0) value_final.num = tr->start_value.num;
|
||||
else if(v == 255) value_final.num = tr->end_value.num;
|
||||
else value_final.num = tr->start_value.num + ((int32_t)((int32_t)(tr->end_value.num - tr->start_value.num) * v) >> 8);
|
||||
break;
|
||||
}
|
||||
|
||||
lv_style_value_t old_value;
|
||||
bool refr = true;
|
||||
if(lv_style_get_prop(obj->styles[i].style, tr->prop, &old_value)) {
|
||||
if(value_final.ptr == old_value.ptr && value_final.color.full == old_value.color.full &&
|
||||
value_final.num == old_value.num) {
|
||||
refr = false;
|
||||
}
|
||||
}
|
||||
lv_style_set_prop(obj->styles[i].style, tr->prop, value_final);
|
||||
if(refr) lv_obj_refresh_style(tr->obj, tr->selector, tr->prop);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void trans_anim_start_cb(lv_anim_t * a)
|
||||
{
|
||||
trans_t * tr = a->var;
|
||||
|
||||
lv_part_t part = lv_obj_style_get_selector_part(tr->selector);
|
||||
tr->start_value = lv_obj_get_style_prop(tr->obj, part, tr->prop);
|
||||
|
||||
/*Init prop to an invalid values to be sure `trans_del` won't delete this added `tr`*/
|
||||
lv_style_prop_t prop_tmp = tr->prop;
|
||||
tr->prop = LV_STYLE_PROP_INV;
|
||||
|
||||
/*Delete the related transitions if any*/
|
||||
trans_del(tr->obj, part, prop_tmp, tr);
|
||||
|
||||
tr->prop = prop_tmp;
|
||||
|
||||
_lv_obj_style_t * style_trans = get_trans_style(tr->obj, tr->selector);
|
||||
lv_style_set_prop(style_trans->style, tr->prop, tr->start_value); /*Be sure `trans_style` has a valid value*/
|
||||
|
||||
}
|
||||
|
||||
static void trans_anim_ready_cb(lv_anim_t * a)
|
||||
{
|
||||
trans_t * tr = a->var;
|
||||
lv_obj_t * obj = tr->obj;
|
||||
lv_style_prop_t prop = tr->prop;
|
||||
|
||||
/*Remove the transitioned property from trans. style
|
||||
*if there no more transitions for this property
|
||||
*It allows changing it by normal styles*/
|
||||
bool running = false;
|
||||
trans_t * tr_i;
|
||||
_LV_LL_READ(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr_i) {
|
||||
if(tr_i != tr && tr_i->obj == tr->obj && tr_i->selector == tr->selector && tr_i->prop == tr->prop) {
|
||||
running = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!running) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans && obj->styles[i].selector == tr->selector) {
|
||||
_lv_ll_remove(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr);
|
||||
lv_mem_free(tr);
|
||||
|
||||
_lv_obj_style_t * obj_style = &obj->styles[i];
|
||||
lv_style_remove_prop(obj_style->style, prop);
|
||||
|
||||
if(lv_style_is_empty(obj->styles[i].style)) {
|
||||
lv_obj_remove_style(obj, obj_style->style, obj_style->selector);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static lv_layer_type_t calculate_layer_type(lv_obj_t * obj)
|
||||
{
|
||||
if(lv_obj_get_style_transform_angle(obj, 0) != 0) return LV_LAYER_TYPE_TRANSFORM;
|
||||
if(lv_obj_get_style_transform_zoom(obj, 0) != 256) return LV_LAYER_TYPE_TRANSFORM;
|
||||
if(lv_obj_get_style_opa(obj, 0) != LV_OPA_COVER) return LV_LAYER_TYPE_SIMPLE;
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(lv_obj_get_style_blend_mode(obj, 0) != LV_BLEND_MODE_NORMAL) return LV_LAYER_TYPE_SIMPLE;
|
||||
#endif
|
||||
return LV_LAYER_TYPE_NONE;
|
||||
}
|
||||
|
||||
static void fade_anim_cb(void * obj, int32_t v)
|
||||
{
|
||||
lv_obj_set_style_opa(obj, v, 0);
|
||||
}
|
||||
|
||||
static void fade_in_anim_ready(lv_anim_t * a)
|
||||
{
|
||||
lv_obj_remove_local_style_prop(a->var, LV_STYLE_OPA, 0);
|
||||
}
|
||||
|
||||
|
||||
248
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_style.h
Normal file
248
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_style.h
Normal file
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
* @file lv_obj_style.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_STYLE_H
|
||||
#define LV_OBJ_STYLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#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);
|
||||
|
||||
void lv_obj_set_local_style_prop_meta(struct _lv_obj_t * obj, lv_style_prop_t prop, uint16_t meta,
|
||||
lv_style_selector_t selector);
|
||||
|
||||
lv_style_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 for color filtering
|
||||
*/
|
||||
lv_style_value_t _lv_obj_style_apply_color_filter(const struct _lv_obj_t * obj, uint32_t part, lv_style_value_t v);
|
||||
|
||||
/**
|
||||
* 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*/
|
||||
@@ -0,0 +1,673 @@
|
||||
#include "lv_obj.h"
|
||||
|
||||
void lv_obj_set_style_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_min_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_MIN_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_max_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_MAX_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_HEIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_min_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_MIN_HEIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_max_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_MAX_HEIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_X, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_Y, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_align(struct _lv_obj_t * obj, lv_align_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ALIGN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transform_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transform_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_HEIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_translate_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSLATE_X, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_translate_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSLATE_Y, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transform_zoom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_ZOOM, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transform_angle(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_ANGLE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transform_pivot_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_PIVOT_X, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transform_pivot_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_PIVOT_Y, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_TOP, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_BOTTOM, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_left(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_LEFT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_right(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_RIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_row(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_ROW, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_COLUMN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_grad_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_grad_dir(struct _lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_DIR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_main_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_MAIN_STOP, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_grad_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_STOP, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_grad(struct _lv_obj_t * obj, const lv_grad_dsc_t * value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_dither_mode(struct _lv_obj_t * obj, lv_dither_mode_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_DITHER_MODE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_SRC, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_RECOLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_RECOLOR_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_tiled(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_TILED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_side(struct _lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_SIDE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_post(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_POST, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_outline_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_outline_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_outline_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_outline_pad(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_PAD, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_ofs_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OFS_X, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_ofs_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OFS_Y, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_spread(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_SPREAD, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_IMG_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_IMG_RECOLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_IMG_RECOLOR_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_DASH_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_DASH_GAP, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_ROUNDED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_ROUNDED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_IMG_SRC, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_font(struct _lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_FONT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_letter_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_LETTER_SPACE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_line_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_LINE_SPACE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_decor(struct _lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_DECOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_align(struct _lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_ALIGN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_radius(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_RADIUS, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_clip_corner(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_CLIP_CORNER, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OPA, v, 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)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_COLOR_FILTER_DSC, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_COLOR_FILTER_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_anim(struct _lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM_TIME, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM_SPEED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSITION, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_blend_mode(struct _lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BLEND_MODE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_layout(struct _lv_obj_t * obj, uint16_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LAYOUT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_base_dir(struct _lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BASE_DIR, v, selector);
|
||||
}
|
||||
@@ -0,0 +1,648 @@
|
||||
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_transform_pivot_x(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_PIVOT_X);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_transform_pivot_y(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_PIVOT_Y);
|
||||
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_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR));
|
||||
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_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR));
|
||||
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_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR));
|
||||
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_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR));
|
||||
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_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR));
|
||||
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_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR));
|
||||
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_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR));
|
||||
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_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_COLOR));
|
||||
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_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_COLOR));
|
||||
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_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_COLOR));
|
||||
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 const lv_anim_t * lv_obj_get_style_anim(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM);
|
||||
return (const lv_anim_t *)v.ptr;
|
||||
}
|
||||
|
||||
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_transform_pivot_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_transform_pivot_y(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_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_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_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_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_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_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_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_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_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_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(struct _lv_obj_t * obj, const lv_anim_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);
|
||||
452
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_tree.c
Normal file
452
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_tree.c
Normal file
@@ -0,0 +1,452 @@
|
||||
/**
|
||||
* @file lv_obj_tree.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lv_obj.h"
|
||||
#include "lv_indev.h"
|
||||
#include "../misc/lv_anim.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
#include "../misc/lv_async.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_obj_del_async_cb(void * obj);
|
||||
static void obj_del_core(lv_obj_t * obj);
|
||||
static lv_obj_tree_walk_res_t walk_core(lv_obj_t * obj, lv_obj_tree_walk_cb_t cb, void * user_data);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_obj_del(lv_obj_t * obj)
|
||||
{
|
||||
LV_LOG_TRACE("begin (delete %p)", (void *)obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
lv_obj_t * par = lv_obj_get_parent(obj);
|
||||
if(par) {
|
||||
lv_obj_scrollbar_invalidate(par);
|
||||
}
|
||||
|
||||
lv_disp_t * disp = NULL;
|
||||
bool act_scr_del = false;
|
||||
if(par == NULL) {
|
||||
disp = lv_obj_get_disp(obj);
|
||||
if(!disp) return; /*Shouldn't happen*/
|
||||
if(disp->act_scr == obj) act_scr_del = true;
|
||||
}
|
||||
|
||||
obj_del_core(obj);
|
||||
|
||||
/*Call the ancestor's event handler to the parent to notify it about the child delete*/
|
||||
if(par) {
|
||||
lv_obj_update_layout(par);
|
||||
lv_obj_readjust_scroll(par, LV_ANIM_OFF);
|
||||
lv_obj_scrollbar_invalidate(par);
|
||||
lv_event_send(par, LV_EVENT_CHILD_CHANGED, NULL);
|
||||
lv_event_send(par, LV_EVENT_CHILD_DELETED, NULL);
|
||||
}
|
||||
|
||||
/*Handle if the active screen was deleted*/
|
||||
if(act_scr_del) {
|
||||
LV_LOG_WARN("the active screen was deleted");
|
||||
disp->act_scr = NULL;
|
||||
}
|
||||
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
LV_LOG_TRACE("finished (delete %p)", (void *)obj);
|
||||
}
|
||||
|
||||
void lv_obj_clean(lv_obj_t * obj)
|
||||
{
|
||||
LV_LOG_TRACE("begin (delete %p)", (void *)obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
lv_obj_t * child = lv_obj_get_child(obj, 0);
|
||||
while(child) {
|
||||
obj_del_core(child);
|
||||
child = lv_obj_get_child(obj, 0);
|
||||
}
|
||||
/*Just to remove scroll animations if any*/
|
||||
lv_obj_scroll_to(obj, 0, 0, LV_ANIM_OFF);
|
||||
if(obj->spec_attr) {
|
||||
obj->spec_attr->scroll.x = 0;
|
||||
obj->spec_attr->scroll.y = 0;
|
||||
}
|
||||
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
|
||||
LV_LOG_TRACE("finished (delete %p)", (void *)obj);
|
||||
}
|
||||
|
||||
void lv_obj_del_delayed(lv_obj_t * obj, uint32_t delay_ms)
|
||||
{
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, obj);
|
||||
lv_anim_set_exec_cb(&a, NULL);
|
||||
lv_anim_set_time(&a, 1);
|
||||
lv_anim_set_delay(&a, delay_ms);
|
||||
lv_anim_set_ready_cb(&a, lv_obj_del_anim_ready_cb);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
void lv_obj_del_anim_ready_cb(lv_anim_t * a)
|
||||
{
|
||||
lv_obj_del(a->var);
|
||||
}
|
||||
|
||||
void lv_obj_del_async(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_async_call(lv_obj_del_async_cb, obj);
|
||||
}
|
||||
|
||||
void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_ASSERT_OBJ(parent, MY_CLASS);
|
||||
|
||||
if(obj->parent == NULL) {
|
||||
LV_LOG_WARN("Can't set the parent of a screen");
|
||||
return;
|
||||
}
|
||||
|
||||
if(parent == NULL) {
|
||||
LV_LOG_WARN("Can't set parent == NULL to an object");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
lv_obj_allocate_spec_attr(parent);
|
||||
|
||||
lv_obj_t * old_parent = obj->parent;
|
||||
/*Remove the object from the old parent's child list*/
|
||||
int32_t i;
|
||||
for(i = lv_obj_get_index(obj); i <= (int32_t)lv_obj_get_child_cnt(old_parent) - 2; i++) {
|
||||
old_parent->spec_attr->children[i] = old_parent->spec_attr->children[i + 1];
|
||||
}
|
||||
old_parent->spec_attr->child_cnt--;
|
||||
if(old_parent->spec_attr->child_cnt) {
|
||||
old_parent->spec_attr->children = lv_mem_realloc(old_parent->spec_attr->children,
|
||||
old_parent->spec_attr->child_cnt * (sizeof(lv_obj_t *)));
|
||||
}
|
||||
else {
|
||||
lv_mem_free(old_parent->spec_attr->children);
|
||||
old_parent->spec_attr->children = NULL;
|
||||
}
|
||||
|
||||
/*Add the child to the new parent as the last (newest child)*/
|
||||
parent->spec_attr->child_cnt++;
|
||||
parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children,
|
||||
parent->spec_attr->child_cnt * (sizeof(lv_obj_t *)));
|
||||
parent->spec_attr->children[lv_obj_get_child_cnt(parent) - 1] = obj;
|
||||
|
||||
obj->parent = parent;
|
||||
|
||||
/*Notify the original parent because one of its children is lost*/
|
||||
lv_obj_readjust_scroll(old_parent, LV_ANIM_OFF);
|
||||
lv_obj_scrollbar_invalidate(old_parent);
|
||||
lv_event_send(old_parent, LV_EVENT_CHILD_CHANGED, obj);
|
||||
lv_event_send(old_parent, LV_EVENT_CHILD_DELETED, NULL);
|
||||
|
||||
/*Notify the new parent about the child*/
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj);
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CREATED, NULL);
|
||||
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
void lv_obj_move_to_index(lv_obj_t * obj, int32_t index)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(index < 0) {
|
||||
index = lv_obj_get_child_cnt(lv_obj_get_parent(obj)) + index;
|
||||
}
|
||||
|
||||
const int32_t old_index = lv_obj_get_index(obj);
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
|
||||
if(index < 0) return;
|
||||
if(index >= (int32_t) lv_obj_get_child_cnt(parent)) return;
|
||||
if(index == old_index) return;
|
||||
|
||||
int32_t i = old_index;
|
||||
if(index < old_index) {
|
||||
while(i > index) {
|
||||
parent->spec_attr->children[i] = parent->spec_attr->children[i - 1];
|
||||
i--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while(i < index) {
|
||||
parent->spec_attr->children[i] = parent->spec_attr->children[i + 1];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
parent->spec_attr->children[index] = obj;
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CHANGED, NULL);
|
||||
lv_obj_invalidate(parent);
|
||||
}
|
||||
|
||||
void lv_obj_swap(lv_obj_t * obj1, lv_obj_t * obj2)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj1, MY_CLASS);
|
||||
LV_ASSERT_OBJ(obj2, MY_CLASS);
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj1);
|
||||
lv_obj_t * parent2 = lv_obj_get_parent(obj2);
|
||||
|
||||
uint_fast32_t index1 = lv_obj_get_index(obj1);
|
||||
uint_fast32_t index2 = lv_obj_get_index(obj2);
|
||||
|
||||
lv_event_send(parent2, LV_EVENT_CHILD_DELETED, obj2);
|
||||
lv_event_send(parent, LV_EVENT_CHILD_DELETED, obj1);
|
||||
|
||||
parent->spec_attr->children[index1] = obj2;
|
||||
parent2->spec_attr->children[index2] = obj1;
|
||||
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj2);
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CREATED, obj2);
|
||||
lv_event_send(parent2, LV_EVENT_CHILD_CHANGED, obj1);
|
||||
lv_event_send(parent2, LV_EVENT_CHILD_CREATED, obj1);
|
||||
|
||||
lv_obj_invalidate(parent);
|
||||
|
||||
if(parent != parent2) {
|
||||
lv_obj_invalidate(parent2);
|
||||
}
|
||||
lv_group_swap_obj(obj1, obj2);
|
||||
}
|
||||
|
||||
lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
const lv_obj_t * par = obj;
|
||||
const lv_obj_t * act_par;
|
||||
|
||||
do {
|
||||
act_par = par;
|
||||
par = lv_obj_get_parent(act_par);
|
||||
} while(par != NULL);
|
||||
|
||||
return (lv_obj_t *)act_par;
|
||||
}
|
||||
|
||||
lv_disp_t * lv_obj_get_disp(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
const lv_obj_t * scr;
|
||||
|
||||
if(obj->parent == NULL) scr = obj; /*`obj` is a screen*/
|
||||
else scr = lv_obj_get_screen(obj); /*get the screen of `obj`*/
|
||||
|
||||
lv_disp_t * d;
|
||||
_LV_LL_READ(&LV_GC_ROOT(_lv_disp_ll), d) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < d->screen_cnt; i++) {
|
||||
if(d->screens[i] == scr) return d;
|
||||
}
|
||||
}
|
||||
|
||||
LV_LOG_WARN("No screen found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_obj_get_parent(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj == NULL) return NULL;
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return obj->parent;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, int32_t id)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(obj->spec_attr == NULL) return NULL;
|
||||
|
||||
uint32_t idu;
|
||||
if(id < 0) {
|
||||
id = obj->spec_attr->child_cnt + id;
|
||||
if(id < 0) return NULL;
|
||||
idu = (uint32_t) id;
|
||||
}
|
||||
else {
|
||||
idu = id;
|
||||
}
|
||||
|
||||
if(idu >= obj->spec_attr->child_cnt) return NULL;
|
||||
else return obj->spec_attr->children[id];
|
||||
}
|
||||
|
||||
uint32_t lv_obj_get_child_cnt(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return obj->spec_attr->child_cnt;
|
||||
}
|
||||
|
||||
uint32_t lv_obj_get_index(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
if(parent == NULL) return 0;
|
||||
|
||||
uint32_t i = 0;
|
||||
for(i = 0; i < lv_obj_get_child_cnt(parent); i++) {
|
||||
if(lv_obj_get_child(parent, i) == obj) return i;
|
||||
}
|
||||
|
||||
return 0xFFFFFFFF; /*Shouldn't happen*/
|
||||
}
|
||||
|
||||
void lv_obj_tree_walk(lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data)
|
||||
{
|
||||
walk_core(start_obj, cb, user_data);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_obj_del_async_cb(void * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_del(obj);
|
||||
}
|
||||
|
||||
static void obj_del_core(lv_obj_t * obj)
|
||||
{
|
||||
/*Let the user free the resources used in `LV_EVENT_DELETE`*/
|
||||
lv_res_t res = lv_event_send(obj, LV_EVENT_DELETE, NULL);
|
||||
if(res == LV_RES_INV) return;
|
||||
|
||||
/*Recursively delete the children*/
|
||||
lv_obj_t * child = lv_obj_get_child(obj, 0);
|
||||
while(child) {
|
||||
obj_del_core(child);
|
||||
child = lv_obj_get_child(obj, 0);
|
||||
}
|
||||
|
||||
lv_group_t * group = lv_obj_get_group(obj);
|
||||
|
||||
/*Reset all input devices if the object to delete is used*/
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
while(indev) {
|
||||
if(indev->proc.types.pointer.act_obj == obj || indev->proc.types.pointer.last_obj == obj) {
|
||||
lv_indev_reset(indev, obj);
|
||||
}
|
||||
if(indev->proc.types.pointer.last_pressed == obj) {
|
||||
indev->proc.types.pointer.last_pressed = NULL;
|
||||
}
|
||||
|
||||
if(indev->group == group && obj == lv_indev_get_obj_act()) {
|
||||
lv_indev_reset(indev, obj);
|
||||
}
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
/*All children deleted. Now clean up the object specific data*/
|
||||
_lv_obj_destruct(obj);
|
||||
|
||||
/*Remove the screen for the screen list*/
|
||||
if(obj->parent == NULL) {
|
||||
lv_disp_t * disp = lv_obj_get_disp(obj);
|
||||
uint32_t i;
|
||||
/*Find the screen in the list*/
|
||||
for(i = 0; i < disp->screen_cnt; i++) {
|
||||
if(disp->screens[i] == obj) break;
|
||||
}
|
||||
|
||||
uint32_t id = i;
|
||||
for(i = id; i < disp->screen_cnt - 1; i++) {
|
||||
disp->screens[i] = disp->screens[i + 1];
|
||||
}
|
||||
disp->screen_cnt--;
|
||||
disp->screens = lv_mem_realloc(disp->screens, disp->screen_cnt * sizeof(lv_obj_t *));
|
||||
}
|
||||
/*Remove the object from the child list of its parent*/
|
||||
else {
|
||||
uint32_t id = lv_obj_get_index(obj);
|
||||
uint32_t i;
|
||||
for(i = id; i < obj->parent->spec_attr->child_cnt - 1; i++) {
|
||||
obj->parent->spec_attr->children[i] = obj->parent->spec_attr->children[i + 1];
|
||||
}
|
||||
obj->parent->spec_attr->child_cnt--;
|
||||
obj->parent->spec_attr->children = lv_mem_realloc(obj->parent->spec_attr->children,
|
||||
obj->parent->spec_attr->child_cnt * sizeof(lv_obj_t *));
|
||||
}
|
||||
|
||||
/*Free the object itself*/
|
||||
lv_mem_free(obj);
|
||||
}
|
||||
|
||||
|
||||
static lv_obj_tree_walk_res_t walk_core(lv_obj_t * obj, lv_obj_tree_walk_cb_t cb, void * user_data)
|
||||
{
|
||||
lv_obj_tree_walk_res_t res = LV_OBJ_TREE_WALK_NEXT;
|
||||
|
||||
if(obj == NULL) {
|
||||
lv_disp_t * disp = lv_disp_get_next(NULL);
|
||||
while(disp) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < disp->screen_cnt; i++) {
|
||||
walk_core(disp->screens[i], cb, user_data);
|
||||
}
|
||||
disp = lv_disp_get_next(disp);
|
||||
}
|
||||
return LV_OBJ_TREE_WALK_END; /*The value doesn't matter as it wasn't called recursively*/
|
||||
}
|
||||
|
||||
res = cb(obj, user_data);
|
||||
|
||||
if(res == LV_OBJ_TREE_WALK_END) return LV_OBJ_TREE_WALK_END;
|
||||
|
||||
if(res != LV_OBJ_TREE_WALK_SKIP_CHILDREN) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < lv_obj_get_child_cnt(obj); i++) {
|
||||
res = walk_core(lv_obj_get_child(obj, i), cb, user_data);
|
||||
if(res == LV_OBJ_TREE_WALK_END) return LV_OBJ_TREE_WALK_END;
|
||||
}
|
||||
}
|
||||
return LV_OBJ_TREE_WALK_NEXT;
|
||||
}
|
||||
172
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_tree.h
Normal file
172
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_obj_tree.h
Normal file
@@ -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 <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*********************
|
||||
* 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*/
|
||||
1255
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_refr.c
Normal file
1255
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_refr.c
Normal file
File diff suppressed because it is too large
Load Diff
115
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_refr.h
Normal file
115
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_refr.h
Normal file
@@ -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 <stdbool.h>
|
||||
|
||||
/*********************
|
||||
* 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_obj_redraw(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*/
|
||||
118
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_theme.c
Normal file
118
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_theme.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @file lv_theme.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lvgl.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void apply_theme(lv_theme_t * th, lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj)
|
||||
{
|
||||
lv_disp_t * disp = obj ? lv_obj_get_disp(obj) : lv_disp_get_default();
|
||||
return lv_disp_get_theme(disp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the active theme on an object
|
||||
* @param obj pointer to an object
|
||||
* @param name the name of the theme element to apply. E.g. `LV_THEME_BTN`
|
||||
*/
|
||||
void lv_theme_apply(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
if(th == NULL) return;
|
||||
|
||||
lv_obj_remove_style_all(obj);
|
||||
|
||||
apply_theme(th, obj); /*Apply the theme including the base theme(s)*/
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 base pointer to the base theme
|
||||
*/
|
||||
void lv_theme_set_parent(lv_theme_t * new_theme, lv_theme_t * base)
|
||||
{
|
||||
new_theme->parent = base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback for a theme.
|
||||
* The callback is used to add styles to different objects
|
||||
* @param theme pointer to theme which callback should be set
|
||||
* @param cb pointer to the callback
|
||||
*/
|
||||
void lv_theme_set_apply_cb(lv_theme_t * theme, lv_theme_apply_cb_t apply_cb)
|
||||
{
|
||||
theme->apply_cb = apply_cb;
|
||||
}
|
||||
|
||||
const lv_font_t * lv_theme_get_font_small(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->font_small : LV_FONT_DEFAULT;
|
||||
}
|
||||
|
||||
const lv_font_t * lv_theme_get_font_normal(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->font_normal : LV_FONT_DEFAULT;
|
||||
}
|
||||
|
||||
const lv_font_t * lv_theme_get_font_large(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->font_large : LV_FONT_DEFAULT;
|
||||
}
|
||||
|
||||
lv_color_t lv_theme_get_color_primary(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->color_primary : lv_palette_main(LV_PALETTE_BLUE_GREY);
|
||||
}
|
||||
|
||||
lv_color_t lv_theme_get_color_secondary(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->color_secondary : lv_palette_main(LV_PALETTE_BLUE);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void apply_theme(lv_theme_t * th, lv_obj_t * obj)
|
||||
{
|
||||
if(th->parent) apply_theme(th->parent, obj);
|
||||
if(th->apply_cb) th->apply_cb(th, obj);
|
||||
}
|
||||
120
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_theme.h
Normal file
120
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/core/lv_theme.h
Normal file
@@ -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*/
|
||||
@@ -0,0 +1,6 @@
|
||||
CSRCS += lv_gpu_arm2d.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d"
|
||||
1376
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/arm2d/lv_gpu_arm2d.c
Normal file
1376
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/arm2d/lv_gpu_arm2d.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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*/
|
||||
53
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw.c
Normal file
53
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @file lv_draw.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "sw/lv_draw_sw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_init(void)
|
||||
{
|
||||
/*Nothing to init now*/
|
||||
}
|
||||
|
||||
void lv_draw_wait_for_finish(lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
if(draw_ctx->wait_for_finish) draw_ctx->wait_for_finish(draw_ctx);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
218
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw.h
Normal file
218
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw.h
Normal file
@@ -0,0 +1,218 @@
|
||||
/**
|
||||
* @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"
|
||||
#include "lv_draw_transform.h"
|
||||
#include "lv_draw_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
void * user_data;
|
||||
} lv_draw_mask_t;
|
||||
|
||||
typedef struct _lv_draw_layer_ctx_t {
|
||||
lv_area_t area_full;
|
||||
lv_area_t area_act;
|
||||
lv_coord_t max_row_with_alpha;
|
||||
lv_coord_t max_row_with_no_alpha;
|
||||
void * buf;
|
||||
struct {
|
||||
const lv_area_t * clip_area;
|
||||
lv_area_t * buf_area;
|
||||
void * buf;
|
||||
bool screen_transp;
|
||||
} original;
|
||||
} lv_draw_layer_ctx_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);
|
||||
|
||||
|
||||
/**
|
||||
* Get an area of a transformed image (zoomed and/or rotated)
|
||||
* @param draw_ctx pointer to a draw context
|
||||
* @param dest_area get this area of the result image. It assumes that the original image is placed to the 0;0 position.
|
||||
* @param src_buf the source image
|
||||
* @param src_w width of the source image in [px]
|
||||
* @param src_h height of the source image in [px]
|
||||
* @param src_stride the stride in [px].
|
||||
* @param draw_dsc an `lv_draw_img_dsc_t` descriptor containing the transformation parameters
|
||||
* @param cf the color format of `src_buf`
|
||||
* @param cbuf place the colors of the pixels on `dest_area` here in RGB format
|
||||
* @param abuf place the opacity of the pixels on `dest_area` here
|
||||
*/
|
||||
void (*draw_transform)(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf,
|
||||
lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride,
|
||||
const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf);
|
||||
|
||||
/**
|
||||
* 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_ctx);
|
||||
|
||||
/**
|
||||
* Copy an area from buffer to an other
|
||||
* @param draw_ctx pointer to a draw context
|
||||
* @param dest_buf copy the buffer into this buffer
|
||||
* @param dest_stride the width of the dest_buf in pixels
|
||||
* @param dest_area the destination area
|
||||
* @param src_buf copy from this buffer
|
||||
* @param src_stride the width of src_buf in pixels
|
||||
* @param src_area the source area.
|
||||
*
|
||||
* @note dest_area and src_area must have the same width and height
|
||||
* but can have different x and y position.
|
||||
* @note dest_area and src_area must be clipped to the real dimensions of the buffers
|
||||
*/
|
||||
void (*buffer_copy)(struct _lv_draw_ctx_t * draw_ctx, void * dest_buf, lv_coord_t dest_stride,
|
||||
const lv_area_t * dest_area,
|
||||
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area);
|
||||
|
||||
/**
|
||||
* Initialize a new layer context.
|
||||
* The original buffer and area data are already saved from `draw_ctx` to `layer_ctx`
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_area the coordinates of the layer
|
||||
* @param flags OR-ed flags from @lv_draw_layer_flags_t
|
||||
* @return pointer to the layer context, or NULL on error
|
||||
*/
|
||||
struct _lv_draw_layer_ctx_t * (*layer_init)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags);
|
||||
|
||||
/**
|
||||
* Adjust the layer_ctx and/or draw_ctx based on the `layer_ctx->area_act`.
|
||||
* It's called only if flags has `LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE`
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_ctx pointer to a layer context
|
||||
* @param flags OR-ed flags from @lv_draw_layer_flags_t
|
||||
*/
|
||||
void (*layer_adjust)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags);
|
||||
|
||||
/**
|
||||
* Blend a rendered layer to `layer_ctx->area_act`
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_ctx pointer to a layer context
|
||||
* @param draw_dsc pointer to an image draw descriptor
|
||||
*/
|
||||
void (*layer_blend)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
const lv_draw_img_dsc_t * draw_dsc);
|
||||
|
||||
/**
|
||||
* Destroy a layer context. The original buffer and area data of the `draw_ctx` will be restored
|
||||
* and the `layer_ctx` itself will be freed automatically.
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_ctx pointer to a layer context
|
||||
*/
|
||||
void (*layer_destroy)(struct _lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx);
|
||||
|
||||
/**
|
||||
* Size of a layer context in bytes.
|
||||
*/
|
||||
size_t layer_instance_size;
|
||||
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data;
|
||||
#endif
|
||||
|
||||
} lv_draw_ctx_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_init(void);
|
||||
|
||||
|
||||
void lv_draw_wait_for_finish(lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* POST INCLUDES
|
||||
*********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_H*/
|
||||
25
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw.mk
Normal file
25
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw.mk
Normal file
@@ -0,0 +1,25 @@
|
||||
CSRCS += lv_draw_arc.c
|
||||
CSRCS += lv_draw.c
|
||||
CSRCS += lv_draw_img.c
|
||||
CSRCS += lv_draw_label.c
|
||||
CSRCS += lv_draw_line.c
|
||||
CSRCS += lv_draw_mask.c
|
||||
CSRCS += lv_draw_rect.c
|
||||
CSRCS += lv_draw_transform.c
|
||||
CSRCS += lv_draw_layer.c
|
||||
CSRCS += lv_draw_triangle.c
|
||||
CSRCS += lv_img_buf.c
|
||||
CSRCS += lv_img_cache.c
|
||||
CSRCS += lv_img_decoder.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw"
|
||||
|
||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d/lv_draw_arm2d.mk
|
||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/lv_draw_nxp.mk
|
||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl/lv_draw_sdl.mk
|
||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d/lv_draw_stm32_dma2d.mk
|
||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw/lv_draw_sw.mk
|
||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/swm341_dma2d/lv_draw_swm341_dma2d.mk
|
||||
152
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw_arc.c
Normal file
152
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw_arc.c
Normal file
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @file lv_draw_arc.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "lv_draw_arc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_draw_arc_dsc_t));
|
||||
dsc->width = 1;
|
||||
dsc->opa = LV_OPA_COVER;
|
||||
dsc->color = lv_color_black();
|
||||
}
|
||||
|
||||
void lv_draw_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)
|
||||
{
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
if(dsc->width == 0) return;
|
||||
if(start_angle == end_angle) return;
|
||||
|
||||
draw_ctx->draw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle);
|
||||
|
||||
// const lv_draw_backend_t * backend = lv_draw_backend_get();
|
||||
// backend->draw_arc(center_x, center_y, radius, start_angle, end_angle, clip_area, dsc);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
lv_coord_t rout = radius;
|
||||
|
||||
/*Special case: full arc invalidation */
|
||||
if(end_angle == start_angle + 360) {
|
||||
area->x1 = x - rout;
|
||||
area->y1 = y - rout;
|
||||
area->x2 = x + rout;
|
||||
area->y2 = y + rout;
|
||||
return;
|
||||
}
|
||||
|
||||
if(start_angle > 360) start_angle -= 360;
|
||||
if(end_angle > 360) end_angle -= 360;
|
||||
|
||||
lv_coord_t rin = radius - w;
|
||||
lv_coord_t extra_area = rounded ? w / 2 + 1 : 0;
|
||||
uint8_t start_quarter = start_angle / 90;
|
||||
uint8_t end_quarter = end_angle / 90;
|
||||
|
||||
/*360 deg still counts as quarter 3 (360 / 90 would be 4)*/
|
||||
if(start_quarter == 4) start_quarter = 3;
|
||||
if(end_quarter == 4) end_quarter = 3;
|
||||
|
||||
if(start_quarter == end_quarter && start_angle <= end_angle) {
|
||||
if(start_quarter == 0) {
|
||||
area->y1 = y + ((lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
area->y2 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
}
|
||||
else if(start_quarter == 1) {
|
||||
area->y2 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
area->y1 = y + ((lv_trigo_sin(end_angle) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
}
|
||||
else if(start_quarter == 2) {
|
||||
area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y2 = y + ((lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
area->y1 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
else if(start_quarter == 3) {
|
||||
area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y1 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
|
||||
area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->y2 = y + ((lv_trigo_sin(end_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
}
|
||||
else if(start_quarter == 0 && end_quarter == 1) {
|
||||
area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y1 = y + ((LV_MIN(lv_trigo_sin(end_angle),
|
||||
lv_trigo_sin(start_angle)) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->y2 = y + rout + extra_area;
|
||||
}
|
||||
else if(start_quarter == 1 && end_quarter == 2) {
|
||||
area->x1 = x - rout - extra_area;
|
||||
area->y1 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + ((LV_MAX(lv_trigo_sin(start_angle + 90),
|
||||
lv_trigo_sin(end_angle + 90)) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->y2 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
else if(start_quarter == 2 && end_quarter == 3) {
|
||||
area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y1 = y - rout - extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->y2 = y + (LV_MAX(lv_trigo_sin(end_angle) * rin,
|
||||
lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
else if(start_quarter == 3 && end_quarter == 0) {
|
||||
area->x1 = x + ((LV_MIN(lv_trigo_sin(end_angle + 90),
|
||||
lv_trigo_sin(start_angle + 90)) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y1 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + rout + extra_area;
|
||||
area->y2 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
}
|
||||
else {
|
||||
area->x1 = x - rout;
|
||||
area->y1 = y - rout;
|
||||
area->x2 = x + rout;
|
||||
area->y2 = y + rout;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@@ -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*/
|
||||
364
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw_img.c
Normal file
364
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw_img.c
Normal file
@@ -0,0 +1,364 @@
|
||||
/**
|
||||
* @file lv_draw_img.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_img.h"
|
||||
#include "lv_img_cache.h"
|
||||
#include "../hal/lv_hal_disp.h"
|
||||
#include "../misc/lv_log.h"
|
||||
#include "../core/lv_refr.h"
|
||||
#include "../misc/lv_mem.h"
|
||||
#include "../misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
LV_ATTRIBUTE_FAST_MEM static lv_res_t decode_and_draw(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords, const void * src);
|
||||
|
||||
static void show_error(lv_draw_ctx_t * draw_ctx, const lv_area_t * coords, const char * msg);
|
||||
static void draw_cleanup(_lv_img_cache_entry_t * cache);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_img_dsc_init(lv_draw_img_dsc_t * dsc)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_draw_img_dsc_t));
|
||||
dsc->recolor = lv_color_black();
|
||||
dsc->opa = LV_OPA_COVER;
|
||||
dsc->zoom = LV_IMG_ZOOM_NONE;
|
||||
dsc->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const lv_area_t * coords, const void * src)
|
||||
{
|
||||
if(src == NULL) {
|
||||
LV_LOG_WARN("Image draw: src is NULL");
|
||||
show_error(draw_ctx, coords, "No\ndata");
|
||||
return;
|
||||
}
|
||||
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_res_t res;
|
||||
if(draw_ctx->draw_img) {
|
||||
res = draw_ctx->draw_img(draw_ctx, dsc, coords, src);
|
||||
}
|
||||
else {
|
||||
res = decode_and_draw(draw_ctx, dsc, coords, src);
|
||||
}
|
||||
|
||||
if(res == LV_RES_INV) {
|
||||
LV_LOG_WARN("Image draw error");
|
||||
show_error(draw_ctx, coords, "No\ndata");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
uint8_t px_size = 0;
|
||||
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_UNKNOWN:
|
||||
case LV_IMG_CF_RAW:
|
||||
px_size = 0;
|
||||
break;
|
||||
case LV_IMG_CF_TRUE_COLOR:
|
||||
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED:
|
||||
px_size = LV_COLOR_SIZE;
|
||||
break;
|
||||
case LV_IMG_CF_TRUE_COLOR_ALPHA:
|
||||
px_size = LV_IMG_PX_SIZE_ALPHA_BYTE << 3;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
case LV_IMG_CF_ALPHA_1BIT:
|
||||
px_size = 1;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
case LV_IMG_CF_ALPHA_2BIT:
|
||||
px_size = 2;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
case LV_IMG_CF_ALPHA_4BIT:
|
||||
px_size = 4;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
case LV_IMG_CF_ALPHA_8BIT:
|
||||
px_size = 8;
|
||||
break;
|
||||
default:
|
||||
px_size = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return px_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
bool is_chroma_keyed = false;
|
||||
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED:
|
||||
case LV_IMG_CF_RAW_CHROMA_KEYED:
|
||||
is_chroma_keyed = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
is_chroma_keyed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return is_chroma_keyed;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
bool has_alpha = false;
|
||||
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR_ALPHA:
|
||||
case LV_IMG_CF_RAW_ALPHA:
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
case LV_IMG_CF_ALPHA_1BIT:
|
||||
case LV_IMG_CF_ALPHA_2BIT:
|
||||
case LV_IMG_CF_ALPHA_4BIT:
|
||||
case LV_IMG_CF_ALPHA_8BIT:
|
||||
has_alpha = true;
|
||||
break;
|
||||
default:
|
||||
has_alpha = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return has_alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
lv_img_src_t img_src_type = LV_IMG_SRC_UNKNOWN;
|
||||
|
||||
if(src == NULL) return img_src_type;
|
||||
const uint8_t * u8_p = src;
|
||||
|
||||
/*The first byte shows the type of the image source*/
|
||||
if(u8_p[0] >= 0x20 && u8_p[0] <= 0x7F) {
|
||||
img_src_type = LV_IMG_SRC_FILE; /*If it's an ASCII character then it's file name*/
|
||||
}
|
||||
else if(u8_p[0] >= 0x80) {
|
||||
img_src_type = LV_IMG_SRC_SYMBOL; /*Symbols begins after 0x7F*/
|
||||
}
|
||||
else {
|
||||
img_src_type = LV_IMG_SRC_VARIABLE; /*`lv_img_dsc_t` is draw to the first byte < 0x20*/
|
||||
}
|
||||
|
||||
if(LV_IMG_SRC_UNKNOWN == img_src_type) {
|
||||
LV_LOG_WARN("lv_img_src_get_type: unknown image type");
|
||||
}
|
||||
|
||||
return img_src_type;
|
||||
}
|
||||
|
||||
void lv_draw_img_decoded(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)
|
||||
{
|
||||
if(draw_ctx->draw_img_decoded == NULL) return;
|
||||
|
||||
draw_ctx->draw_img_decoded(draw_ctx, dsc, coords, map_p, color_format);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM static lv_res_t decode_and_draw(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords, const void * src)
|
||||
{
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return LV_RES_OK;
|
||||
|
||||
_lv_img_cache_entry_t * cdsc = _lv_img_cache_open(src, draw_dsc->recolor, draw_dsc->frame_id);
|
||||
|
||||
if(cdsc == NULL) return LV_RES_INV;
|
||||
|
||||
lv_img_cf_t cf;
|
||||
if(lv_img_cf_is_chroma_keyed(cdsc->dec_dsc.header.cf)) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED;
|
||||
else if(LV_IMG_CF_ALPHA_8BIT == cdsc->dec_dsc.header.cf) cf = LV_IMG_CF_ALPHA_8BIT;
|
||||
else if(LV_IMG_CF_RGB565A8 == cdsc->dec_dsc.header.cf) cf = LV_IMG_CF_RGB565A8;
|
||||
else if(lv_img_cf_has_alpha(cdsc->dec_dsc.header.cf)) cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
|
||||
else cf = LV_IMG_CF_TRUE_COLOR;
|
||||
|
||||
if(cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
if(draw_dsc->angle || draw_dsc->zoom != LV_IMG_ZOOM_NONE) {
|
||||
/* resume normal method */
|
||||
cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
|
||||
cdsc->dec_dsc.img_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(cdsc->dec_dsc.error_msg != NULL) {
|
||||
LV_LOG_WARN("Image draw error");
|
||||
|
||||
show_error(draw_ctx, coords, cdsc->dec_dsc.error_msg);
|
||||
}
|
||||
/*The decoder could open the image and gave the entire uncompressed image.
|
||||
*Just draw it!*/
|
||||
else if(cdsc->dec_dsc.img_data) {
|
||||
lv_area_t map_area_rot;
|
||||
lv_area_copy(&map_area_rot, coords);
|
||||
if(draw_dsc->angle || draw_dsc->zoom != LV_IMG_ZOOM_NONE) {
|
||||
int32_t w = lv_area_get_width(coords);
|
||||
int32_t h = lv_area_get_height(coords);
|
||||
|
||||
_lv_img_buf_get_transformed_area(&map_area_rot, w, h, draw_dsc->angle, draw_dsc->zoom, &draw_dsc->pivot);
|
||||
|
||||
map_area_rot.x1 += coords->x1;
|
||||
map_area_rot.y1 += coords->y1;
|
||||
map_area_rot.x2 += coords->x1;
|
||||
map_area_rot.y2 += coords->y1;
|
||||
}
|
||||
|
||||
lv_area_t clip_com; /*Common area of mask and coords*/
|
||||
bool union_ok;
|
||||
union_ok = _lv_area_intersect(&clip_com, draw_ctx->clip_area, &map_area_rot);
|
||||
/*Out of mask. There is nothing to draw so the image is drawn successfully.*/
|
||||
if(union_ok == false) {
|
||||
draw_cleanup(cdsc);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
const lv_area_t * clip_area_ori = draw_ctx->clip_area;
|
||||
draw_ctx->clip_area = &clip_com;
|
||||
lv_draw_img_decoded(draw_ctx, draw_dsc, coords, cdsc->dec_dsc.img_data, cf);
|
||||
draw_ctx->clip_area = clip_area_ori;
|
||||
}
|
||||
/*The whole uncompressed image is not available. Try to read it line-by-line*/
|
||||
else {
|
||||
lv_area_t mask_com; /*Common area of mask and coords*/
|
||||
bool union_ok;
|
||||
union_ok = _lv_area_intersect(&mask_com, draw_ctx->clip_area, coords);
|
||||
/*Out of mask. There is nothing to draw so the image is drawn successfully.*/
|
||||
if(union_ok == false) {
|
||||
draw_cleanup(cdsc);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
int32_t width = lv_area_get_width(&mask_com);
|
||||
|
||||
uint8_t * buf = lv_mem_buf_get(lv_area_get_width(&mask_com) *
|
||||
LV_IMG_PX_SIZE_ALPHA_BYTE); /*+1 because of the possible alpha byte*/
|
||||
|
||||
const lv_area_t * clip_area_ori = draw_ctx->clip_area;
|
||||
lv_area_t line;
|
||||
lv_area_copy(&line, &mask_com);
|
||||
lv_area_set_height(&line, 1);
|
||||
int32_t x = mask_com.x1 - coords->x1;
|
||||
int32_t y = mask_com.y1 - coords->y1;
|
||||
int32_t row;
|
||||
lv_res_t read_res;
|
||||
for(row = mask_com.y1; row <= mask_com.y2; row++) {
|
||||
lv_area_t mask_line;
|
||||
union_ok = _lv_area_intersect(&mask_line, clip_area_ori, &line);
|
||||
if(union_ok == false) continue;
|
||||
|
||||
read_res = lv_img_decoder_read_line(&cdsc->dec_dsc, x, y, width, buf);
|
||||
if(read_res != LV_RES_OK) {
|
||||
lv_img_decoder_close(&cdsc->dec_dsc);
|
||||
LV_LOG_WARN("Image draw can't read the line");
|
||||
lv_mem_buf_release(buf);
|
||||
draw_cleanup(cdsc);
|
||||
draw_ctx->clip_area = clip_area_ori;
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
draw_ctx->clip_area = &mask_line;
|
||||
lv_draw_img_decoded(draw_ctx, draw_dsc, &line, buf, cf);
|
||||
line.y1++;
|
||||
line.y2++;
|
||||
y++;
|
||||
}
|
||||
draw_ctx->clip_area = clip_area_ori;
|
||||
lv_mem_buf_release(buf);
|
||||
}
|
||||
|
||||
draw_cleanup(cdsc);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
static void show_error(lv_draw_ctx_t * draw_ctx, const lv_area_t * coords, const char * msg)
|
||||
{
|
||||
lv_draw_rect_dsc_t rect_dsc;
|
||||
lv_draw_rect_dsc_init(&rect_dsc);
|
||||
rect_dsc.bg_color = lv_color_white();
|
||||
lv_draw_rect(draw_ctx, &rect_dsc, coords);
|
||||
|
||||
lv_draw_label_dsc_t label_dsc;
|
||||
lv_draw_label_dsc_init(&label_dsc);
|
||||
lv_draw_label(draw_ctx, &label_dsc, coords, msg, NULL);
|
||||
}
|
||||
|
||||
static void draw_cleanup(_lv_img_cache_entry_t * cache)
|
||||
{
|
||||
/*Automatically close images with no caching*/
|
||||
#if LV_IMG_CACHE_DEF_SIZE == 0
|
||||
lv_img_decoder_close(&cache->dec_dsc);
|
||||
#else
|
||||
LV_UNUSED(cache);
|
||||
#endif
|
||||
}
|
||||
104
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw_img.h
Normal file
104
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw_img.h
Normal file
@@ -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 {
|
||||
|
||||
int16_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*/
|
||||
417
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw_label.c
Normal file
417
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw_label.c
Normal file
@@ -0,0 +1,417 @@
|
||||
/**
|
||||
* @file lv_draw_label.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "lv_draw_label.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../hal/lv_hal_disp.h"
|
||||
#include "../core/lv_refr.h"
|
||||
#include "../misc/lv_bidi.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LABEL_RECOLOR_PAR_LENGTH 6
|
||||
#define LV_LABEL_HINT_UPDATE_TH 1024 /*Update the "hint" if the label's y coordinates have changed more then this*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
enum {
|
||||
CMD_STATE_WAIT,
|
||||
CMD_STATE_PAR,
|
||||
CMD_STATE_IN,
|
||||
};
|
||||
typedef uint8_t cmd_state_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static uint8_t hex_char_to_num(char hex);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_draw_label_dsc_t));
|
||||
dsc->opa = LV_OPA_COVER;
|
||||
dsc->color = lv_color_black();
|
||||
dsc->font = LV_FONT_DEFAULT;
|
||||
dsc->sel_start = LV_DRAW_LABEL_NO_TXT_SEL;
|
||||
dsc->sel_end = LV_DRAW_LABEL_NO_TXT_SEL;
|
||||
dsc->sel_color = lv_color_black();
|
||||
dsc->sel_bg_color = lv_palette_main(LV_PALETTE_BLUE);
|
||||
dsc->bidi_dir = LV_BASE_DIR_LTR;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(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)
|
||||
{
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
if(dsc->font == NULL) {
|
||||
LV_LOG_WARN("dsc->font == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if(draw_ctx->draw_letter == NULL) {
|
||||
LV_LOG_WARN("draw->draw_letter == NULL (there is no function to draw letters)");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_draw_label_dsc_t dsc_mod = *dsc;
|
||||
|
||||
const lv_font_t * font = dsc->font;
|
||||
int32_t w;
|
||||
|
||||
/*No need to waste processor time if string is empty*/
|
||||
if(txt == NULL || txt[0] == '\0')
|
||||
return;
|
||||
|
||||
lv_area_t clipped_area;
|
||||
bool clip_ok = _lv_area_intersect(&clipped_area, coords, draw_ctx->clip_area);
|
||||
if(!clip_ok) return;
|
||||
|
||||
lv_text_align_t align = dsc->align;
|
||||
lv_base_dir_t base_dir = dsc->bidi_dir;
|
||||
|
||||
lv_bidi_calculate_align(&align, &base_dir, txt);
|
||||
|
||||
if((dsc->flag & LV_TEXT_FLAG_EXPAND) == 0) {
|
||||
/*Normally use the label's width as width*/
|
||||
w = lv_area_get_width(coords);
|
||||
}
|
||||
else {
|
||||
/*If EXPAND is enabled then not limit the text's width to the object's width*/
|
||||
lv_point_t p;
|
||||
lv_txt_get_size(&p, txt, dsc->font, dsc->letter_space, dsc->line_space, LV_COORD_MAX,
|
||||
dsc->flag);
|
||||
w = p.x;
|
||||
}
|
||||
|
||||
int32_t line_height_font = lv_font_get_line_height(font);
|
||||
int32_t line_height = line_height_font + dsc->line_space;
|
||||
|
||||
/*Init variables for the first line*/
|
||||
int32_t line_width = 0;
|
||||
lv_point_t pos;
|
||||
pos.x = coords->x1;
|
||||
pos.y = coords->y1;
|
||||
|
||||
int32_t x_ofs = 0;
|
||||
int32_t y_ofs = 0;
|
||||
x_ofs = dsc->ofs_x;
|
||||
y_ofs = dsc->ofs_y;
|
||||
pos.y += y_ofs;
|
||||
|
||||
uint32_t line_start = 0;
|
||||
int32_t last_line_start = -1;
|
||||
|
||||
/*Check the hint to use the cached info*/
|
||||
if(hint && y_ofs == 0 && coords->y1 < 0) {
|
||||
/*If the label changed too much recalculate the hint.*/
|
||||
if(LV_ABS(hint->coord_y - coords->y1) > LV_LABEL_HINT_UPDATE_TH - 2 * line_height) {
|
||||
hint->line_start = -1;
|
||||
}
|
||||
last_line_start = hint->line_start;
|
||||
}
|
||||
|
||||
/*Use the hint if it's valid*/
|
||||
if(hint && last_line_start >= 0) {
|
||||
line_start = last_line_start;
|
||||
pos.y += hint->y;
|
||||
}
|
||||
|
||||
uint32_t line_end = line_start + _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, NULL, dsc->flag);
|
||||
|
||||
/*Go the first visible line*/
|
||||
while(pos.y + line_height_font < draw_ctx->clip_area->y1) {
|
||||
/*Go to next line*/
|
||||
line_start = line_end;
|
||||
line_end += _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, NULL, dsc->flag);
|
||||
pos.y += line_height;
|
||||
|
||||
/*Save at the threshold coordinate*/
|
||||
if(hint && pos.y >= -LV_LABEL_HINT_UPDATE_TH && hint->line_start < 0) {
|
||||
hint->line_start = line_start;
|
||||
hint->y = pos.y - coords->y1;
|
||||
hint->coord_y = coords->y1;
|
||||
}
|
||||
|
||||
if(txt[line_start] == '\0') return;
|
||||
}
|
||||
|
||||
/*Align to middle*/
|
||||
if(align == LV_TEXT_ALIGN_CENTER) {
|
||||
line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
|
||||
pos.x += (lv_area_get_width(coords) - line_width) / 2;
|
||||
|
||||
}
|
||||
/*Align to the right*/
|
||||
else if(align == LV_TEXT_ALIGN_RIGHT) {
|
||||
line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
pos.x += lv_area_get_width(coords) - line_width;
|
||||
}
|
||||
uint32_t sel_start = dsc->sel_start;
|
||||
uint32_t sel_end = dsc->sel_end;
|
||||
if(sel_start > sel_end) {
|
||||
uint32_t tmp = sel_start;
|
||||
sel_start = sel_end;
|
||||
sel_end = tmp;
|
||||
}
|
||||
lv_draw_line_dsc_t line_dsc;
|
||||
|
||||
if((dsc->decor & LV_TEXT_DECOR_UNDERLINE) || (dsc->decor & LV_TEXT_DECOR_STRIKETHROUGH)) {
|
||||
lv_draw_line_dsc_init(&line_dsc);
|
||||
line_dsc.color = dsc->color;
|
||||
line_dsc.width = font->underline_thickness ? font->underline_thickness : 1;
|
||||
line_dsc.opa = dsc->opa;
|
||||
line_dsc.blend_mode = dsc->blend_mode;
|
||||
}
|
||||
|
||||
cmd_state_t cmd_state = CMD_STATE_WAIT;
|
||||
uint32_t i;
|
||||
uint32_t par_start = 0;
|
||||
lv_color_t recolor = lv_color_black();
|
||||
lv_color_t color = lv_color_black();
|
||||
int32_t letter_w;
|
||||
|
||||
lv_draw_rect_dsc_t draw_dsc_sel;
|
||||
lv_draw_rect_dsc_init(&draw_dsc_sel);
|
||||
draw_dsc_sel.bg_color = dsc->sel_bg_color;
|
||||
|
||||
int32_t pos_x_start = pos.x;
|
||||
/*Write out all lines*/
|
||||
while(txt[line_start] != '\0') {
|
||||
pos.x += x_ofs;
|
||||
|
||||
/*Write all letter of a line*/
|
||||
cmd_state = CMD_STATE_WAIT;
|
||||
i = 0;
|
||||
#if LV_USE_BIDI
|
||||
char * bidi_txt = lv_mem_buf_get(line_end - line_start + 1);
|
||||
_lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, base_dir, NULL, 0);
|
||||
#else
|
||||
const char * bidi_txt = txt + line_start;
|
||||
#endif
|
||||
|
||||
while(i < line_end - line_start) {
|
||||
uint32_t logical_char_pos = 0;
|
||||
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
|
||||
#if LV_USE_BIDI
|
||||
logical_char_pos = _lv_txt_encoded_get_char_id(txt, line_start);
|
||||
uint32_t t = _lv_txt_encoded_get_char_id(bidi_txt, i);
|
||||
logical_char_pos += _lv_bidi_get_logical_pos(bidi_txt, NULL, line_end - line_start, base_dir, t, NULL);
|
||||
#else
|
||||
logical_char_pos = _lv_txt_encoded_get_char_id(txt, line_start + i);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t letter;
|
||||
uint32_t letter_next;
|
||||
_lv_txt_encoded_letter_next_2(bidi_txt, &letter, &letter_next, &i);
|
||||
/*Handle the re-color command*/
|
||||
if((dsc->flag & LV_TEXT_FLAG_RECOLOR) != 0) {
|
||||
if(letter == (uint32_t)LV_TXT_COLOR_CMD[0]) {
|
||||
if(cmd_state == CMD_STATE_WAIT) { /*Start char*/
|
||||
par_start = i;
|
||||
cmd_state = CMD_STATE_PAR;
|
||||
continue;
|
||||
}
|
||||
else if(cmd_state == CMD_STATE_PAR) { /*Other start char in parameter escaped cmd. char*/
|
||||
cmd_state = CMD_STATE_WAIT;
|
||||
}
|
||||
else if(cmd_state == CMD_STATE_IN) { /*Command end*/
|
||||
cmd_state = CMD_STATE_WAIT;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*Skip the color parameter and wait the space after it*/
|
||||
if(cmd_state == CMD_STATE_PAR) {
|
||||
if(letter == ' ') {
|
||||
/*Get the parameter*/
|
||||
if(i - par_start == LABEL_RECOLOR_PAR_LENGTH + 1) {
|
||||
char buf[LABEL_RECOLOR_PAR_LENGTH + 1];
|
||||
lv_memcpy_small(buf, &bidi_txt[par_start], LABEL_RECOLOR_PAR_LENGTH);
|
||||
buf[LABEL_RECOLOR_PAR_LENGTH] = '\0';
|
||||
int r, g, b;
|
||||
r = (hex_char_to_num(buf[0]) << 4) + hex_char_to_num(buf[1]);
|
||||
g = (hex_char_to_num(buf[2]) << 4) + hex_char_to_num(buf[3]);
|
||||
b = (hex_char_to_num(buf[4]) << 4) + hex_char_to_num(buf[5]);
|
||||
recolor = lv_color_make(r, g, b);
|
||||
}
|
||||
else {
|
||||
recolor.full = dsc->color.full;
|
||||
}
|
||||
cmd_state = CMD_STATE_IN; /*After the parameter the text is in the command*/
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
color = dsc->color;
|
||||
|
||||
if(cmd_state == CMD_STATE_IN) color = recolor;
|
||||
|
||||
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
|
||||
|
||||
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
|
||||
if(logical_char_pos >= sel_start && logical_char_pos < sel_end) {
|
||||
lv_area_t sel_coords;
|
||||
sel_coords.x1 = pos.x;
|
||||
sel_coords.y1 = pos.y;
|
||||
sel_coords.x2 = pos.x + letter_w + dsc->letter_space - 1;
|
||||
sel_coords.y2 = pos.y + line_height - 1;
|
||||
lv_draw_rect(draw_ctx, &draw_dsc_sel, &sel_coords);
|
||||
color = dsc->sel_color;
|
||||
}
|
||||
}
|
||||
|
||||
dsc_mod.color = color;
|
||||
lv_draw_letter(draw_ctx, &dsc_mod, &pos, letter);
|
||||
|
||||
if(letter_w > 0) {
|
||||
pos.x += letter_w + dsc->letter_space;
|
||||
}
|
||||
}
|
||||
|
||||
if(dsc->decor & LV_TEXT_DECOR_STRIKETHROUGH) {
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
p1.x = pos_x_start;
|
||||
p1.y = pos.y + (dsc->font->line_height / 2) + line_dsc.width / 2;
|
||||
p2.x = pos.x;
|
||||
p2.y = p1.y;
|
||||
line_dsc.color = color;
|
||||
lv_draw_line(draw_ctx, &line_dsc, &p1, &p2);
|
||||
}
|
||||
|
||||
if(dsc->decor & LV_TEXT_DECOR_UNDERLINE) {
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
p1.x = pos_x_start;
|
||||
p1.y = pos.y + dsc->font->line_height - dsc->font->base_line - font->underline_position;
|
||||
p2.x = pos.x;
|
||||
p2.y = p1.y;
|
||||
line_dsc.color = color;
|
||||
lv_draw_line(draw_ctx, &line_dsc, &p1, &p2);
|
||||
}
|
||||
|
||||
#if LV_USE_BIDI
|
||||
lv_mem_buf_release(bidi_txt);
|
||||
bidi_txt = NULL;
|
||||
#endif
|
||||
/*Go to next line*/
|
||||
line_start = line_end;
|
||||
line_end += _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, NULL, dsc->flag);
|
||||
|
||||
pos.x = coords->x1;
|
||||
/*Align to middle*/
|
||||
if(align == LV_TEXT_ALIGN_CENTER) {
|
||||
line_width =
|
||||
lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
|
||||
pos.x += (lv_area_get_width(coords) - line_width) / 2;
|
||||
|
||||
}
|
||||
/*Align to the right*/
|
||||
else if(align == LV_TEXT_ALIGN_RIGHT) {
|
||||
line_width =
|
||||
lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
pos.x += lv_area_get_width(coords) - line_width;
|
||||
}
|
||||
|
||||
/*Go the next line position*/
|
||||
pos.y += line_height;
|
||||
|
||||
if(pos.y > draw_ctx->clip_area->y2) return;
|
||||
}
|
||||
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
}
|
||||
|
||||
void lv_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
|
||||
uint32_t letter)
|
||||
{
|
||||
draw_ctx->draw_letter(draw_ctx, dsc, pos_p, letter);
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Convert a hexadecimal characters to a number (0..15)
|
||||
* @param hex Pointer to a hexadecimal character (0..9, A..F)
|
||||
* @return the numerical value of `hex` or 0 on error
|
||||
*/
|
||||
static uint8_t hex_char_to_num(char hex)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
|
||||
if(hex >= '0' && hex <= '9') {
|
||||
result = hex - '0';
|
||||
}
|
||||
else {
|
||||
if(hex >= 'a') hex -= 'a' - 'A'; /*Convert to upper case*/
|
||||
|
||||
switch(hex) {
|
||||
case 'A':
|
||||
result = 10;
|
||||
break;
|
||||
case 'B':
|
||||
result = 11;
|
||||
break;
|
||||
case 'C':
|
||||
result = 12;
|
||||
break;
|
||||
case 'D':
|
||||
result = 13;
|
||||
break;
|
||||
case 'E':
|
||||
result = 14;
|
||||
break;
|
||||
case 'F':
|
||||
result = 15;
|
||||
break;
|
||||
default:
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
100
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw_label.h
Normal file
100
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw_label.h
Normal file
@@ -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*/
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @file lv_draw_layer.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "lv_draw_arc.h"
|
||||
#include "../core/lv_refr.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_draw_layer_ctx_t * lv_draw_layer_create(lv_draw_ctx_t * draw_ctx, const lv_area_t * layer_area,
|
||||
lv_draw_layer_flags_t flags)
|
||||
{
|
||||
if(draw_ctx->layer_init == NULL) return NULL;
|
||||
|
||||
lv_draw_layer_ctx_t * layer_ctx = lv_mem_alloc(draw_ctx->layer_instance_size);
|
||||
LV_ASSERT_MALLOC(layer_ctx);
|
||||
if(layer_ctx == NULL) {
|
||||
LV_LOG_WARN("Couldn't allocate a new layer context");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_memset_00(layer_ctx, draw_ctx->layer_instance_size);
|
||||
|
||||
lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing();
|
||||
layer_ctx->original.buf = draw_ctx->buf;
|
||||
layer_ctx->original.buf_area = draw_ctx->buf_area;
|
||||
layer_ctx->original.clip_area = draw_ctx->clip_area;
|
||||
layer_ctx->original.screen_transp = disp_refr->driver->screen_transp;
|
||||
layer_ctx->area_full = *layer_area;
|
||||
|
||||
lv_draw_layer_ctx_t * init_layer_ctx = draw_ctx->layer_init(draw_ctx, layer_ctx, flags);
|
||||
if(NULL == init_layer_ctx) {
|
||||
lv_mem_free(layer_ctx);
|
||||
}
|
||||
return init_layer_ctx;
|
||||
}
|
||||
|
||||
void lv_draw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags)
|
||||
{
|
||||
if(draw_ctx->layer_adjust) draw_ctx->layer_adjust(draw_ctx, layer_ctx, flags);
|
||||
}
|
||||
|
||||
void lv_draw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_img_dsc_t * draw_dsc)
|
||||
{
|
||||
if(draw_ctx->layer_blend) draw_ctx->layer_blend(draw_ctx, layer_ctx, draw_dsc);
|
||||
}
|
||||
|
||||
void lv_draw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx)
|
||||
{
|
||||
|
||||
lv_draw_wait_for_finish(draw_ctx);
|
||||
draw_ctx->buf = layer_ctx->original.buf;
|
||||
draw_ctx->buf_area = layer_ctx->original.buf_area;
|
||||
draw_ctx->clip_area = layer_ctx->original.clip_area;
|
||||
lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing();
|
||||
disp_refr->driver->screen_transp = layer_ctx->original.screen_transp;
|
||||
|
||||
if(draw_ctx->layer_destroy) draw_ctx->layer_destroy(draw_ctx, layer_ctx);
|
||||
lv_mem_free(layer_ctx);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* @file lv_draw_layer.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_LAYER_H
|
||||
#define LV_DRAW_LAYER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
struct _lv_draw_ctx_t;
|
||||
struct _lv_draw_layer_ctx_t;
|
||||
|
||||
typedef enum {
|
||||
LV_DRAW_LAYER_FLAG_NONE,
|
||||
LV_DRAW_LAYER_FLAG_HAS_ALPHA,
|
||||
LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE,
|
||||
} lv_draw_layer_flags_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a new layer context. It is used to start and independent rendering session
|
||||
* with the current draw_ctx
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_area the coordinates of the layer
|
||||
* @param flags OR-ed flags from @lv_draw_layer_flags_t
|
||||
* @return pointer to the layer context, or NULL on error
|
||||
*/
|
||||
struct _lv_draw_layer_ctx_t * lv_draw_layer_create(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * layer_area,
|
||||
lv_draw_layer_flags_t flags);
|
||||
|
||||
/**
|
||||
* Adjust the layer_ctx and/or draw_ctx based on the `layer_ctx->area_act`.
|
||||
* It's called only if flags has `LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE`
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_ctx pointer to a layer context
|
||||
* @param flags OR-ed flags from @lv_draw_layer_flags_t
|
||||
*/
|
||||
void lv_draw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags);
|
||||
|
||||
/**
|
||||
* Blend a rendered layer to `layer_ctx->area_act`
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_ctx pointer to a layer context
|
||||
* @param draw_dsc pointer to an image draw descriptor
|
||||
*/
|
||||
void lv_draw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_img_dsc_t * draw_dsc);
|
||||
|
||||
/**
|
||||
* Destroy a layer context.
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_ctx pointer to a layer context
|
||||
*/
|
||||
void lv_draw_layer_destroy(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_LAYER_H*/
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @file lv_draw_line.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
#include "../core/lv_refr.h"
|
||||
#include "../misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_draw_line_dsc_t));
|
||||
dsc->width = 1;
|
||||
dsc->opa = LV_OPA_COVER;
|
||||
dsc->color = lv_color_black();
|
||||
}
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM 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)
|
||||
{
|
||||
if(dsc->width == 0) return;
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
draw_ctx->draw_line(draw_ctx, dsc, point1, point2);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@@ -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*/
|
||||
1530
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw_mask.c
Normal file
1530
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw_mask.c
Normal file
File diff suppressed because it is too large
Load Diff
394
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw_mask.h
Normal file
394
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_draw_mask.h
Normal file
@@ -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 <stdbool.h>
|
||||
#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*/
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* @file lv_draw_rect.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "lv_draw_rect.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_draw_rect_dsc_t));
|
||||
dsc->bg_color = lv_color_white();
|
||||
dsc->bg_grad.stops[0].color = lv_color_white();
|
||||
dsc->bg_grad.stops[1].color = lv_color_black();
|
||||
dsc->bg_grad.stops[1].frac = 0xFF;
|
||||
dsc->bg_grad.stops_count = 2;
|
||||
dsc->border_color = lv_color_black();
|
||||
dsc->shadow_color = lv_color_black();
|
||||
dsc->bg_img_symbol_font = LV_FONT_DEFAULT;
|
||||
dsc->bg_opa = LV_OPA_COVER;
|
||||
dsc->bg_img_opa = LV_OPA_COVER;
|
||||
dsc->outline_opa = LV_OPA_COVER;
|
||||
dsc->border_opa = LV_OPA_COVER;
|
||||
dsc->shadow_opa = LV_OPA_COVER;
|
||||
dsc->border_side = LV_BORDER_SIDE_FULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a rectangle
|
||||
* @param coords the coordinates of the rectangle
|
||||
* @param mask the rectangle will be drawn only in this mask
|
||||
* @param dsc pointer to an initialized `lv_draw_rect_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
if(lv_area_get_height(coords) < 1 || lv_area_get_width(coords) < 1) return;
|
||||
|
||||
draw_ctx->draw_rect(draw_ctx, dsc, coords);
|
||||
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @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;
|
||||
lv_color_t bg_color; /**< First element of a gradient is a color, so it maps well here*/
|
||||
lv_grad_dsc_t bg_grad;
|
||||
|
||||
/*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*/
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @file lv_draw_transform.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "lv_draw_transform.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "../misc/lv_area.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
void lv_draw_transform(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf, lv_coord_t src_w,
|
||||
lv_coord_t src_h,
|
||||
lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf)
|
||||
{
|
||||
LV_ASSERT_NULL(draw_ctx);
|
||||
if(draw_ctx->draw_transform == NULL) {
|
||||
LV_LOG_WARN("draw_ctx->draw_transform == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
draw_ctx->draw_transform(draw_ctx, dest_area, src_buf, src_w, src_h, src_stride, draw_dsc, cf, cbuf, abuf);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @file lv_draw_transform.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_TRANSFORM_H
|
||||
#define LV_DRAW_TRANSFORM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
#include "../misc/lv_area.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
struct _lv_draw_ctx_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_transform(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf,
|
||||
lv_coord_t src_w, lv_coord_t src_h,
|
||||
lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_TRANSFORM_H*/
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @file lv_draw_triangle.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "lv_draw_triangle.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../misc/lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
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)
|
||||
{
|
||||
draw_ctx->draw_polygon(draw_ctx, draw_dsc, points, 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[])
|
||||
{
|
||||
|
||||
draw_ctx->draw_polygon(draw_ctx, draw_dsc, points, 3);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@@ -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*/
|
||||
463
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_img_buf.c
Normal file
463
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_img_buf.c
Normal file
@@ -0,0 +1,463 @@
|
||||
/**
|
||||
* @file lv_img_buf.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "lv_img_buf.h"
|
||||
#include "lv_draw_img.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../misc/lv_log.h"
|
||||
#include "../misc/lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
lv_color_t p_color = lv_color_black();
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED ||
|
||||
dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA || dsc->header.cf == LV_IMG_CF_RGB565A8) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
lv_memcpy_small(&p_color, &buf_u8[px], sizeof(lv_color_t));
|
||||
#if LV_COLOR_SIZE == 32
|
||||
p_color.ch.alpha = 0xFF; /*Only the color should be get so use a default alpha value*/
|
||||
#endif
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) {
|
||||
buf_u8 += 4 * 2;
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 8, 16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
p_color.full = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) {
|
||||
buf_u8 += 4 * 4;
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned
|
||||
*so the possible real width are 4, 8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
p_color.full = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) {
|
||||
buf_u8 += 4 * 16;
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned
|
||||
*so the possible real width are 2, 4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
p_color.full = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
buf_u8 += 4 * 256;
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
p_color.full = buf_u8[px];
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT ||
|
||||
dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
p_color = color;
|
||||
}
|
||||
return p_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)
|
||||
{
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint32_t px = dsc->header.w * y * LV_IMG_PX_SIZE_ALPHA_BYTE + x * LV_IMG_PX_SIZE_ALPHA_BYTE;
|
||||
return buf_u8[px + LV_IMG_PX_SIZE_ALPHA_BYTE - 1];
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) {
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit);
|
||||
return px_opa ? LV_OPA_TRANSP : LV_OPA_COVER;
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) {
|
||||
const uint8_t opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/
|
||||
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 4 ,8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit);
|
||||
return opa_table[px_opa];
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) {
|
||||
const uint8_t opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/
|
||||
68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255
|
||||
};
|
||||
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit);
|
||||
return opa_table[px_opa];
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
return buf_u8[px];
|
||||
}
|
||||
|
||||
return LV_OPA_COVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
buf_u8[px + px_size - 1] = opa;
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) {
|
||||
opa = opa >> 7; /*opa -> [0,1]*/
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0x1) << (7 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) {
|
||||
opa = opa >> 6; /*opa -> [0,3]*/
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 4 ,8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0x3) << (6 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) {
|
||||
opa = opa >> 4; /*opa -> [0,15]*/
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0xF) << (4 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
buf_u8[px] = opa;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
lv_memcpy_small(&buf_u8[px], &c, px_size);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
lv_memcpy_small(&buf_u8[px], &c, px_size - 1); /*-1 to not overwrite the alpha value*/
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 2; /*Skip the palette*/
|
||||
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0x1) << (7 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 4; /*Skip the palette*/
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned
|
||||
*so the possible real width are 4, 8 ,12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
|
||||
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0x3) << (6 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 16; /*Skip the palette*/
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned
|
||||
*so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0xF) << (4 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 256; /*Skip the palette*/
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
buf_u8[px] = c.full;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if((dsc->header.cf == LV_IMG_CF_ALPHA_1BIT && id > 1) || (dsc->header.cf == LV_IMG_CF_ALPHA_2BIT && id > 3) ||
|
||||
(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT && id > 15) || (dsc->header.cf == LV_IMG_CF_ALPHA_8BIT)) {
|
||||
LV_LOG_WARN("lv_img_buf_set_px_alpha: invalid 'id'");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_color32_t c32;
|
||||
c32.full = lv_color_to32(c);
|
||||
uint8_t * buf = (uint8_t *)dsc->data;
|
||||
lv_memcpy_small(&buf[id * sizeof(c32)], &c32, sizeof(c32));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
/*Allocate image descriptor*/
|
||||
lv_img_dsc_t * dsc = lv_mem_alloc(sizeof(lv_img_dsc_t));
|
||||
if(dsc == NULL)
|
||||
return NULL;
|
||||
|
||||
lv_memset_00(dsc, sizeof(lv_img_dsc_t));
|
||||
|
||||
/*Get image data size*/
|
||||
dsc->data_size = lv_img_buf_get_img_size(w, h, cf);
|
||||
if(dsc->data_size == 0) {
|
||||
lv_mem_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*Allocate raw buffer*/
|
||||
dsc->data = lv_mem_alloc(dsc->data_size);
|
||||
if(dsc->data == NULL) {
|
||||
lv_mem_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
lv_memset_00((uint8_t *)dsc->data, dsc->data_size);
|
||||
|
||||
/*Fill in header*/
|
||||
dsc->header.always_zero = 0;
|
||||
dsc->header.w = w;
|
||||
dsc->header.h = h;
|
||||
dsc->header.cf = cf;
|
||||
return dsc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free an allocated image buffer
|
||||
* @param dsc image buffer to free
|
||||
*/
|
||||
void lv_img_buf_free(lv_img_dsc_t * dsc)
|
||||
{
|
||||
if(dsc != NULL) {
|
||||
if(dsc->data != NULL)
|
||||
lv_mem_free((void *)dsc->data);
|
||||
|
||||
lv_mem_free(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)
|
||||
{
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR:
|
||||
return LV_IMG_BUF_SIZE_TRUE_COLOR(w, h);
|
||||
case LV_IMG_CF_TRUE_COLOR_ALPHA:
|
||||
case LV_IMG_CF_RGB565A8:
|
||||
return LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h);
|
||||
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED:
|
||||
return LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h);
|
||||
case LV_IMG_CF_ALPHA_1BIT:
|
||||
return LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_2BIT:
|
||||
return LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_4BIT:
|
||||
return LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_8BIT:
|
||||
return LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
return LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
return LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
return LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
return LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(angle == 0 && zoom == LV_IMG_ZOOM_NONE) {
|
||||
res->x1 = 0;
|
||||
res->y1 = 0;
|
||||
res->x2 = w - 1;
|
||||
res->y2 = h - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
lv_point_t p[4] = {
|
||||
{0, 0},
|
||||
{w, 0},
|
||||
{0, h},
|
||||
{w, h},
|
||||
};
|
||||
lv_point_transform(&p[0], angle, zoom, pivot);
|
||||
lv_point_transform(&p[1], angle, zoom, pivot);
|
||||
lv_point_transform(&p[2], angle, zoom, pivot);
|
||||
lv_point_transform(&p[3], angle, zoom, pivot);
|
||||
res->x1 = LV_MIN4(p[0].x, p[1].x, p[2].x, p[3].x) - 2;
|
||||
res->x2 = LV_MAX4(p[0].x, p[1].x, p[2].x, p[3].x) + 2;
|
||||
res->y1 = LV_MIN4(p[0].y, p[1].y, p[2].y, p[3].y) - 2;
|
||||
res->y2 = LV_MAX4(p[0].y, p[1].y, p[2].y, p[3].y) + 2;
|
||||
|
||||
#else
|
||||
LV_UNUSED(angle);
|
||||
LV_UNUSED(zoom);
|
||||
LV_UNUSED(pivot);
|
||||
res->x1 = 0;
|
||||
res->y1 = 0;
|
||||
res->x2 = w - 1;
|
||||
res->y2 = h - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
249
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_img_buf.h
Normal file
249
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_img_buf.h
Normal file
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* @file lv_img_buf.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_IMG_BUF_H
|
||||
#define LV_IMG_BUF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
#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_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 (can't be chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_2BIT, /**< Can have 4 different colors in a palette (can't be chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_4BIT, /**< Can have 16 different colors in a palette (can't be chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_8BIT, /**< Can have 256 different colors in a palette (can't be 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_RGB888,
|
||||
LV_IMG_CF_RGBA8888,
|
||||
LV_IMG_CF_RGBX8888,
|
||||
LV_IMG_CF_RGB565,
|
||||
LV_IMG_CF_RGBA5658,
|
||||
LV_IMG_CF_RGB565A8,
|
||||
|
||||
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;
|
||||
|
||||
/**********************
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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*/
|
||||
215
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_img_cache.c
Normal file
215
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_img_cache.c
Normal file
@@ -0,0 +1,215 @@
|
||||
/**
|
||||
* @file lv_img_cache.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "lv_img_cache.h"
|
||||
#include "lv_img_decoder.h"
|
||||
#include "lv_draw_img.h"
|
||||
#include "../hal/lv_hal_tick.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*Decrement life with this value on every open*/
|
||||
#define LV_IMG_CACHE_AGING 1
|
||||
|
||||
/*Boost life by this factor (multiply time_to_open with this value)*/
|
||||
#define LV_IMG_CACHE_LIFE_GAIN 1
|
||||
|
||||
/*Don't let life to be greater than this limit because it would require a lot of time to
|
||||
* "die" from very high values*/
|
||||
#define LV_IMG_CACHE_LIFE_LIMIT 1000
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static bool lv_img_cache_match(const void * src1, const void * src2);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static uint16_t entry_cnt;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* 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 color The color of the image with `LV_IMG_CF_ALPHA_...`
|
||||
* @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)
|
||||
{
|
||||
/*Is the image cached?*/
|
||||
_lv_img_cache_entry_t * cached_src = NULL;
|
||||
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
if(entry_cnt == 0) {
|
||||
LV_LOG_WARN("lv_img_cache_open: the cache size is 0");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array);
|
||||
|
||||
/*Decrement all lifes. Make the entries older*/
|
||||
uint16_t i;
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(cache[i].life > INT32_MIN + LV_IMG_CACHE_AGING) {
|
||||
cache[i].life -= LV_IMG_CACHE_AGING;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(color.full == cache[i].dec_dsc.color.full &&
|
||||
frame_id == cache[i].dec_dsc.frame_id &&
|
||||
lv_img_cache_match(src, cache[i].dec_dsc.src)) {
|
||||
/*If opened increment its life.
|
||||
*Image difficult to open should live longer to keep avoid frequent their recaching.
|
||||
*Therefore increase `life` with `time_to_open`*/
|
||||
cached_src = &cache[i];
|
||||
cached_src->life += cached_src->dec_dsc.time_to_open * LV_IMG_CACHE_LIFE_GAIN;
|
||||
if(cached_src->life > LV_IMG_CACHE_LIFE_LIMIT) cached_src->life = LV_IMG_CACHE_LIFE_LIMIT;
|
||||
LV_LOG_TRACE("image source found in the cache");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*The image is not cached then cache it now*/
|
||||
if(cached_src) return cached_src;
|
||||
|
||||
/*Find an entry to reuse. Select the entry with the least life*/
|
||||
cached_src = &cache[0];
|
||||
for(i = 1; i < entry_cnt; i++) {
|
||||
if(cache[i].life < cached_src->life) {
|
||||
cached_src = &cache[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*Close the decoder to reuse if it was opened (has a valid source)*/
|
||||
if(cached_src->dec_dsc.src) {
|
||||
lv_img_decoder_close(&cached_src->dec_dsc);
|
||||
LV_LOG_INFO("image draw: cache miss, close and reuse an entry");
|
||||
}
|
||||
else {
|
||||
LV_LOG_INFO("image draw: cache miss, cached to an empty entry");
|
||||
}
|
||||
#else
|
||||
cached_src = &LV_GC_ROOT(_lv_img_cache_single);
|
||||
#endif
|
||||
/*Open the image and measure the time to open*/
|
||||
uint32_t t_start = lv_tick_get();
|
||||
lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, color, frame_id);
|
||||
if(open_res == LV_RES_INV) {
|
||||
LV_LOG_WARN("Image draw cannot open the image resource");
|
||||
lv_memset_00(cached_src, sizeof(_lv_img_cache_entry_t));
|
||||
cached_src->life = INT32_MIN; /*Make the empty entry very "weak" to force its us*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cached_src->life = 0;
|
||||
|
||||
/*If `time_to_open` was not set in the open function set it here*/
|
||||
if(cached_src->dec_dsc.time_to_open == 0) {
|
||||
cached_src->dec_dsc.time_to_open = lv_tick_elaps(t_start);
|
||||
}
|
||||
|
||||
if(cached_src->dec_dsc.time_to_open == 0) cached_src->dec_dsc.time_to_open = 1;
|
||||
|
||||
return cached_src;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_entry_cnt)
|
||||
{
|
||||
#if LV_IMG_CACHE_DEF_SIZE == 0
|
||||
LV_UNUSED(new_entry_cnt);
|
||||
LV_LOG_WARN("Can't change cache size because it's disabled by LV_IMG_CACHE_DEF_SIZE = 0");
|
||||
#else
|
||||
if(LV_GC_ROOT(_lv_img_cache_array) != NULL) {
|
||||
/*Clean the cache before free it*/
|
||||
lv_img_cache_invalidate_src(NULL);
|
||||
lv_mem_free(LV_GC_ROOT(_lv_img_cache_array));
|
||||
}
|
||||
|
||||
/*Reallocate the cache*/
|
||||
LV_GC_ROOT(_lv_img_cache_array) = lv_mem_alloc(sizeof(_lv_img_cache_entry_t) * new_entry_cnt);
|
||||
LV_ASSERT_MALLOC(LV_GC_ROOT(_lv_img_cache_array));
|
||||
if(LV_GC_ROOT(_lv_img_cache_array) == NULL) {
|
||||
entry_cnt = 0;
|
||||
return;
|
||||
}
|
||||
entry_cnt = new_entry_cnt;
|
||||
|
||||
/*Clean the cache*/
|
||||
lv_memset_00(LV_GC_ROOT(_lv_img_cache_array), entry_cnt * sizeof(_lv_img_cache_entry_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
LV_UNUSED(src);
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
_lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array);
|
||||
|
||||
uint16_t i;
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(src == NULL || lv_img_cache_match(src, cache[i].dec_dsc.src)) {
|
||||
if(cache[i].dec_dsc.src != NULL) {
|
||||
lv_img_decoder_close(&cache[i].dec_dsc);
|
||||
}
|
||||
|
||||
lv_memset_00(&cache[i], sizeof(_lv_img_cache_entry_t));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static bool lv_img_cache_match(const void * src1, const void * src2)
|
||||
{
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src1);
|
||||
if(src_type == LV_IMG_SRC_VARIABLE)
|
||||
return src1 == src2;
|
||||
if(src_type != LV_IMG_SRC_FILE)
|
||||
return false;
|
||||
if(lv_img_src_get_type(src2) != LV_IMG_SRC_FILE)
|
||||
return false;
|
||||
return strcmp(src1, src2) == 0;
|
||||
}
|
||||
#endif
|
||||
@@ -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*/
|
||||
705
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_img_decoder.c
Normal file
705
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_img_decoder.c
Normal file
@@ -0,0 +1,705 @@
|
||||
/**
|
||||
* @file lv_img_decoder.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_img_decoder.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "../draw/lv_draw_img.h"
|
||||
#include "../misc/lv_ll.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define CF_BUILT_IN_FIRST LV_IMG_CF_TRUE_COLOR
|
||||
#define CF_BUILT_IN_LAST LV_IMG_CF_RGB565A8
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_fs_file_t f;
|
||||
lv_color_t * palette;
|
||||
lv_opa_t * opa;
|
||||
} lv_img_decoder_built_in_data_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_img_decoder_built_in_line_true_color(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf);
|
||||
static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf);
|
||||
static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the image decoder module
|
||||
*/
|
||||
void _lv_img_decoder_init(void)
|
||||
{
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_img_decoder_ll), sizeof(lv_img_decoder_t));
|
||||
|
||||
lv_img_decoder_t * decoder;
|
||||
|
||||
/*Create a decoder for the built in color format*/
|
||||
decoder = lv_img_decoder_create();
|
||||
LV_ASSERT_MALLOC(decoder);
|
||||
if(decoder == NULL) {
|
||||
LV_LOG_WARN("lv_img_decoder_init: out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_img_decoder_set_info_cb(decoder, lv_img_decoder_built_in_info);
|
||||
lv_img_decoder_set_open_cb(decoder, lv_img_decoder_built_in_open);
|
||||
lv_img_decoder_set_read_line_cb(decoder, lv_img_decoder_built_in_read_line);
|
||||
lv_img_decoder_set_close_cb(decoder, lv_img_decoder_built_in_close);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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. E.g. file name or variable.
|
||||
* @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)
|
||||
{
|
||||
lv_memset_00(header, sizeof(lv_img_header_t));
|
||||
|
||||
if(src == NULL) return LV_RES_INV;
|
||||
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src);
|
||||
if(src_type == LV_IMG_SRC_VARIABLE) {
|
||||
const lv_img_dsc_t * img_dsc = src;
|
||||
if(img_dsc->data == NULL) return LV_RES_INV;
|
||||
}
|
||||
|
||||
lv_res_t res = LV_RES_INV;
|
||||
lv_img_decoder_t * d;
|
||||
_LV_LL_READ(&LV_GC_ROOT(_lv_img_decoder_ll), d) {
|
||||
if(d->info_cb) {
|
||||
res = d->info_cb(d, src, header);
|
||||
if(res == LV_RES_OK) break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_color_t color, int32_t frame_id)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_img_decoder_dsc_t));
|
||||
|
||||
if(src == NULL) return LV_RES_INV;
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src);
|
||||
if(src_type == LV_IMG_SRC_VARIABLE) {
|
||||
const lv_img_dsc_t * img_dsc = src;
|
||||
if(img_dsc->data == NULL) return LV_RES_INV;
|
||||
}
|
||||
|
||||
dsc->color = color;
|
||||
dsc->src_type = src_type;
|
||||
dsc->frame_id = frame_id;
|
||||
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
size_t fnlen = strlen(src);
|
||||
dsc->src = lv_mem_alloc(fnlen + 1);
|
||||
LV_ASSERT_MALLOC(dsc->src);
|
||||
if(dsc->src == NULL) {
|
||||
LV_LOG_WARN("lv_img_decoder_open: out of memory");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
strcpy((char *)dsc->src, src);
|
||||
}
|
||||
else {
|
||||
dsc->src = src;
|
||||
}
|
||||
|
||||
lv_res_t res = LV_RES_INV;
|
||||
|
||||
lv_img_decoder_t * decoder;
|
||||
_LV_LL_READ(&LV_GC_ROOT(_lv_img_decoder_ll), decoder) {
|
||||
/*Info and Open callbacks are required*/
|
||||
if(decoder->info_cb == NULL || decoder->open_cb == NULL) continue;
|
||||
|
||||
res = decoder->info_cb(decoder, src, &dsc->header);
|
||||
if(res != LV_RES_OK) continue;
|
||||
|
||||
dsc->decoder = decoder;
|
||||
res = decoder->open_cb(decoder, dsc);
|
||||
|
||||
/*Opened successfully. It is a good decoder for this image source*/
|
||||
if(res == LV_RES_OK) return res;
|
||||
|
||||
/*Prepare for the next loop*/
|
||||
lv_memset_00(&dsc->header, sizeof(lv_img_header_t));
|
||||
|
||||
dsc->error_msg = NULL;
|
||||
dsc->img_data = NULL;
|
||||
dsc->user_data = NULL;
|
||||
dsc->time_to_open = 0;
|
||||
}
|
||||
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE)
|
||||
lv_mem_free((void *)dsc->src);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
lv_res_t res = LV_RES_INV;
|
||||
if(dsc->decoder->read_line_cb) res = dsc->decoder->read_line_cb(dsc->decoder, dsc, x, y, len, buf);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if(dsc->decoder) {
|
||||
if(dsc->decoder->close_cb) dsc->decoder->close_cb(dsc->decoder, dsc);
|
||||
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
lv_mem_free((void *)dsc->src);
|
||||
dsc->src = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new image decoder
|
||||
* @return pointer to the new image decoder
|
||||
*/
|
||||
lv_img_decoder_t * lv_img_decoder_create(void)
|
||||
{
|
||||
lv_img_decoder_t * decoder;
|
||||
decoder = _lv_ll_ins_head(&LV_GC_ROOT(_lv_img_decoder_ll));
|
||||
LV_ASSERT_MALLOC(decoder);
|
||||
if(decoder == NULL) return NULL;
|
||||
|
||||
lv_memset_00(decoder, sizeof(lv_img_decoder_t));
|
||||
|
||||
return decoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an image decoder
|
||||
* @param decoder pointer to an image decoder
|
||||
*/
|
||||
void lv_img_decoder_delete(lv_img_decoder_t * decoder)
|
||||
{
|
||||
_lv_ll_remove(&LV_GC_ROOT(_lv_img_decoder_ll), decoder);
|
||||
lv_mem_free(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)
|
||||
{
|
||||
decoder->info_cb = 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)
|
||||
{
|
||||
decoder->open_cb = 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)
|
||||
{
|
||||
decoder->read_line_cb = 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)
|
||||
{
|
||||
decoder->close_cb = 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)
|
||||
{
|
||||
LV_UNUSED(decoder); /*Unused*/
|
||||
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src);
|
||||
if(src_type == LV_IMG_SRC_VARIABLE) {
|
||||
lv_img_cf_t cf = ((lv_img_dsc_t *)src)->header.cf;
|
||||
if(cf < CF_BUILT_IN_FIRST || cf > CF_BUILT_IN_LAST) return LV_RES_INV;
|
||||
|
||||
header->w = ((lv_img_dsc_t *)src)->header.w;
|
||||
header->h = ((lv_img_dsc_t *)src)->header.h;
|
||||
header->cf = ((lv_img_dsc_t *)src)->header.cf;
|
||||
}
|
||||
else if(src_type == LV_IMG_SRC_FILE) {
|
||||
/*Support only "*.bin" files*/
|
||||
if(strcmp(lv_fs_get_ext(src), "bin")) return LV_RES_INV;
|
||||
|
||||
lv_fs_file_t f;
|
||||
lv_fs_res_t res = lv_fs_open(&f, src, LV_FS_MODE_RD);
|
||||
if(res == LV_FS_RES_OK) {
|
||||
uint32_t rn;
|
||||
res = lv_fs_read(&f, header, sizeof(lv_img_header_t), &rn);
|
||||
lv_fs_close(&f);
|
||||
if(res != LV_FS_RES_OK || rn != sizeof(lv_img_header_t)) {
|
||||
LV_LOG_WARN("Image get info get read file header");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
if(header->cf < CF_BUILT_IN_FIRST || header->cf > CF_BUILT_IN_LAST) return LV_RES_INV;
|
||||
}
|
||||
else if(src_type == LV_IMG_SRC_SYMBOL) {
|
||||
/*The size depend on the font but it is unknown here. It should be handled outside of the
|
||||
*function*/
|
||||
header->w = 1;
|
||||
header->h = 1;
|
||||
/*Symbols always have transparent parts. Important because of cover check in the draw
|
||||
*function. The actual value doesn't matter because lv_draw_label will draw it*/
|
||||
header->cf = LV_IMG_CF_ALPHA_1BIT;
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Image get info found unknown src type");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a built in image
|
||||
* @param decoder the decoder where this function belongs
|
||||
* @param dsc pointer to decoder descriptor. `src`, `color` 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)
|
||||
{
|
||||
/*Open the file if it's a file*/
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
/*Support only "*.bin" files*/
|
||||
if(strcmp(lv_fs_get_ext(dsc->src), "bin")) return LV_RES_INV;
|
||||
|
||||
lv_fs_file_t f;
|
||||
lv_fs_res_t res = lv_fs_open(&f, dsc->src, LV_FS_MODE_RD);
|
||||
if(res != LV_FS_RES_OK) {
|
||||
LV_LOG_WARN("Built-in image decoder can't open the file");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
/*If the file was open successfully save the file descriptor*/
|
||||
if(dsc->user_data == NULL) {
|
||||
dsc->user_data = lv_mem_alloc(sizeof(lv_img_decoder_built_in_data_t));
|
||||
LV_ASSERT_MALLOC(dsc->user_data);
|
||||
if(dsc->user_data == NULL) {
|
||||
LV_LOG_ERROR("img_decoder_built_in_open: out of memory");
|
||||
lv_fs_close(&f);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
lv_memset_00(dsc->user_data, sizeof(lv_img_decoder_built_in_data_t));
|
||||
}
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
lv_memcpy_small(&user_data->f, &f, sizeof(f));
|
||||
}
|
||||
else if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
|
||||
/*The variables should have valid data*/
|
||||
if(((lv_img_dsc_t *)dsc->src)->data == NULL) {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
lv_img_cf_t cf = dsc->header.cf;
|
||||
/*Process true color formats*/
|
||||
if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_ALPHA ||
|
||||
cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED || cf == LV_IMG_CF_RGB565A8 ||
|
||||
cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
|
||||
/*In case of uncompressed formats the image stored in the ROM/RAM.
|
||||
*So simply give its pointer*/
|
||||
dsc->img_data = ((lv_img_dsc_t *)dsc->src)->data;
|
||||
return LV_RES_OK;
|
||||
}
|
||||
else {
|
||||
/*If it's a file it need to be read line by line later*/
|
||||
return LV_RES_OK;
|
||||
}
|
||||
}
|
||||
/*Process indexed images. Build a palette*/
|
||||
else if(cf == LV_IMG_CF_INDEXED_1BIT || cf == LV_IMG_CF_INDEXED_2BIT || cf == LV_IMG_CF_INDEXED_4BIT ||
|
||||
cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(cf);
|
||||
uint32_t palette_size = 1 << px_size;
|
||||
|
||||
/*Allocate the palette*/
|
||||
if(dsc->user_data == NULL) {
|
||||
dsc->user_data = lv_mem_alloc(sizeof(lv_img_decoder_built_in_data_t));
|
||||
LV_ASSERT_MALLOC(dsc->user_data);
|
||||
if(dsc->user_data == NULL) {
|
||||
LV_LOG_ERROR("img_decoder_built_in_open: out of memory");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
lv_memset_00(dsc->user_data, sizeof(lv_img_decoder_built_in_data_t));
|
||||
}
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
user_data->palette = lv_mem_alloc(palette_size * sizeof(lv_color_t));
|
||||
LV_ASSERT_MALLOC(user_data->palette);
|
||||
user_data->opa = lv_mem_alloc(palette_size * sizeof(lv_opa_t));
|
||||
LV_ASSERT_MALLOC(user_data->opa);
|
||||
if(user_data->palette == NULL || user_data->opa == NULL) {
|
||||
LV_LOG_ERROR("img_decoder_built_in_open: out of memory");
|
||||
lv_img_decoder_built_in_close(decoder, dsc);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
/*Read the palette from file*/
|
||||
lv_fs_seek(&user_data->f, 4, LV_FS_SEEK_SET); /*Skip the header*/
|
||||
lv_color32_t cur_color;
|
||||
uint32_t i;
|
||||
for(i = 0; i < palette_size; i++) {
|
||||
lv_fs_read(&user_data->f, &cur_color, sizeof(lv_color32_t), NULL);
|
||||
user_data->palette[i] = lv_color_make(cur_color.ch.red, cur_color.ch.green, cur_color.ch.blue);
|
||||
user_data->opa[i] = cur_color.ch.alpha;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*The palette begins in the beginning of the image data. Just point to it.*/
|
||||
lv_color32_t * palette_p = (lv_color32_t *)((lv_img_dsc_t *)dsc->src)->data;
|
||||
|
||||
uint32_t i;
|
||||
for(i = 0; i < palette_size; i++) {
|
||||
user_data->palette[i] = lv_color_make(palette_p[i].ch.red, palette_p[i].ch.green, palette_p[i].ch.blue);
|
||||
user_data->opa[i] = palette_p[i].ch.alpha;
|
||||
}
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
/*Alpha indexed images.*/
|
||||
else if(cf == LV_IMG_CF_ALPHA_1BIT || cf == LV_IMG_CF_ALPHA_2BIT || cf == LV_IMG_CF_ALPHA_4BIT) {
|
||||
return LV_RES_OK; /*Nothing to process*/
|
||||
}
|
||||
/*Unknown format. Can't decode it.*/
|
||||
else {
|
||||
/*Free the potentially allocated memories*/
|
||||
lv_img_decoder_built_in_close(decoder, dsc);
|
||||
|
||||
LV_LOG_WARN("Image decoder open: unknown color format");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
LV_UNUSED(decoder); /*Unused*/
|
||||
|
||||
lv_res_t res = LV_RES_INV;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA ||
|
||||
dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
/*For TRUE_COLOR images read line required only for files.
|
||||
*For variables the image data was returned in `open`*/
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
res = lv_img_decoder_built_in_line_true_color(dsc, x, y, len, buf);
|
||||
}
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT ||
|
||||
dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
res = lv_img_decoder_built_in_line_alpha(dsc, x, y, len, buf);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT || dsc->header.cf == LV_IMG_CF_INDEXED_2BIT ||
|
||||
dsc->header.cf == LV_IMG_CF_INDEXED_4BIT || dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
res = lv_img_decoder_built_in_line_indexed(dsc, x, y, len, buf);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Built-in image decoder read not supports the color format");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
LV_UNUSED(decoder); /*Unused*/
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
if(user_data) {
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
lv_fs_close(&user_data->f);
|
||||
}
|
||||
if(user_data->palette) lv_mem_free(user_data->palette);
|
||||
if(user_data->opa) lv_mem_free(user_data->opa);
|
||||
|
||||
lv_mem_free(user_data);
|
||||
dsc->user_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_res_t lv_img_decoder_built_in_line_true_color(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf)
|
||||
{
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
lv_fs_res_t res;
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf);
|
||||
|
||||
uint32_t pos = ((y * dsc->header.w + x) * px_size) >> 3;
|
||||
pos += 4; /*Skip the header*/
|
||||
res = lv_fs_seek(&user_data->f, pos, LV_FS_SEEK_SET);
|
||||
if(res != LV_FS_RES_OK) {
|
||||
LV_LOG_WARN("Built-in image decoder seek failed");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
uint32_t btr = len * (px_size >> 3);
|
||||
uint32_t br = 0;
|
||||
res = lv_fs_read(&user_data->f, buf, btr, &br);
|
||||
if(res != LV_FS_RES_OK || btr != br) {
|
||||
LV_LOG_WARN("Built-in image decoder read failed");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf)
|
||||
{
|
||||
const lv_opa_t alpha1_opa_table[2] = {0, 255}; /*Opacity mapping with bpp = 1 (Just for compatibility)*/
|
||||
const lv_opa_t alpha2_opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/
|
||||
const lv_opa_t alpha4_opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/
|
||||
68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255
|
||||
};
|
||||
|
||||
/*Simply fill the buffer with the color. Later only the alpha value will be modified.*/
|
||||
lv_color_t bg_color = dsc->color;
|
||||
lv_coord_t i;
|
||||
for(i = 0; i < len; i++) {
|
||||
#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = bg_color.full;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
/*Because of Alpha byte 16 bit color can start on odd address which can cause crash*/
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = bg_color.full & 0xFF;
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + 1] = (bg_color.full >> 8) & 0xFF;
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
*((uint32_t *)&buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE]) = bg_color.full;
|
||||
#else
|
||||
#error "Invalid LV_COLOR_DEPTH. Check it in lv_conf.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
const lv_opa_t * opa_table = NULL;
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf);
|
||||
uint16_t mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/
|
||||
|
||||
lv_coord_t w = 0;
|
||||
uint32_t ofs = 0;
|
||||
int8_t pos = 0;
|
||||
switch(dsc->header.cf) {
|
||||
case LV_IMG_CF_ALPHA_1BIT:
|
||||
w = (dsc->header.w + 7) >> 3; /*E.g. w = 20 -> w = 2 + 1*/
|
||||
ofs += w * y + (x >> 3); /*First pixel*/
|
||||
pos = 7 - (x & 0x7);
|
||||
opa_table = alpha1_opa_table;
|
||||
break;
|
||||
case LV_IMG_CF_ALPHA_2BIT:
|
||||
w = (dsc->header.w + 3) >> 2; /*E.g. w = 13 -> w = 3 + 1 (bytes)*/
|
||||
ofs += w * y + (x >> 2); /*First pixel*/
|
||||
pos = 6 - (x & 0x3) * 2;
|
||||
opa_table = alpha2_opa_table;
|
||||
break;
|
||||
case LV_IMG_CF_ALPHA_4BIT:
|
||||
w = (dsc->header.w + 1) >> 1; /*E.g. w = 13 -> w = 6 + 1 (bytes)*/
|
||||
ofs += w * y + (x >> 1); /*First pixel*/
|
||||
pos = 4 - (x & 0x1) * 4;
|
||||
opa_table = alpha4_opa_table;
|
||||
break;
|
||||
case LV_IMG_CF_ALPHA_8BIT:
|
||||
w = dsc->header.w; /*E.g. x = 7 -> w = 7 (bytes)*/
|
||||
ofs += w * y + x; /*First pixel*/
|
||||
pos = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
uint8_t * fs_buf = lv_mem_buf_get(w);
|
||||
if(fs_buf == NULL) return LV_RES_INV;
|
||||
|
||||
const uint8_t * data_tmp = NULL;
|
||||
if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
|
||||
const lv_img_dsc_t * img_dsc = dsc->src;
|
||||
|
||||
data_tmp = img_dsc->data + ofs;
|
||||
}
|
||||
else {
|
||||
lv_fs_seek(&user_data->f, ofs + 4, LV_FS_SEEK_SET); /*+4 to skip the header*/
|
||||
lv_fs_read(&user_data->f, fs_buf, w, NULL);
|
||||
data_tmp = fs_buf;
|
||||
}
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
uint8_t val_act = (*data_tmp >> pos) & mask;
|
||||
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + LV_IMG_PX_SIZE_ALPHA_BYTE - 1] =
|
||||
dsc->header.cf == LV_IMG_CF_ALPHA_8BIT ? val_act : opa_table[val_act];
|
||||
|
||||
pos -= px_size;
|
||||
if(pos < 0) {
|
||||
pos = 8 - px_size;
|
||||
data_tmp++;
|
||||
}
|
||||
}
|
||||
lv_mem_buf_release(fs_buf);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf)
|
||||
{
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf);
|
||||
uint16_t mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/
|
||||
|
||||
lv_coord_t w = 0;
|
||||
int8_t pos = 0;
|
||||
uint32_t ofs = 0;
|
||||
switch(dsc->header.cf) {
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
w = (dsc->header.w + 7) >> 3; /*E.g. w = 20 -> w = 2 + 1*/
|
||||
ofs += w * y + (x >> 3); /*First pixel*/
|
||||
ofs += 8; /*Skip the palette*/
|
||||
pos = 7 - (x & 0x7);
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
w = (dsc->header.w + 3) >> 2; /*E.g. w = 13 -> w = 3 + 1 (bytes)*/
|
||||
ofs += w * y + (x >> 2); /*First pixel*/
|
||||
ofs += 16; /*Skip the palette*/
|
||||
pos = 6 - (x & 0x3) * 2;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
w = (dsc->header.w + 1) >> 1; /*E.g. w = 13 -> w = 6 + 1 (bytes)*/
|
||||
ofs += w * y + (x >> 1); /*First pixel*/
|
||||
ofs += 64; /*Skip the palette*/
|
||||
pos = 4 - (x & 0x1) * 4;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
w = dsc->header.w; /*E.g. x = 7 -> w = 7 (bytes)*/
|
||||
ofs += w * y + x; /*First pixel*/
|
||||
ofs += 1024; /*Skip the palette*/
|
||||
pos = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
|
||||
uint8_t * fs_buf = lv_mem_buf_get(w);
|
||||
if(fs_buf == NULL) return LV_RES_INV;
|
||||
const uint8_t * data_tmp = NULL;
|
||||
if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
|
||||
const lv_img_dsc_t * img_dsc = dsc->src;
|
||||
data_tmp = img_dsc->data + ofs;
|
||||
}
|
||||
else {
|
||||
lv_fs_seek(&user_data->f, ofs + 4, LV_FS_SEEK_SET); /*+4 to skip the header*/
|
||||
lv_fs_read(&user_data->f, fs_buf, w, NULL);
|
||||
data_tmp = fs_buf;
|
||||
}
|
||||
|
||||
lv_coord_t i;
|
||||
for(i = 0; i < len; i++) {
|
||||
uint8_t val_act = (*data_tmp >> pos) & mask;
|
||||
|
||||
lv_color_t color = user_data->palette[val_act];
|
||||
#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = color.full;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
/*Because of Alpha byte 16 bit color can start on odd address which can cause crash*/
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = color.full & 0xFF;
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + 1] = (color.full >> 8) & 0xFF;
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
*((uint32_t *)&buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE]) = color.full;
|
||||
#else
|
||||
#error "Invalid LV_COLOR_DEPTH. Check it in lv_conf.h"
|
||||
#endif
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + LV_IMG_PX_SIZE_ALPHA_BYTE - 1] = user_data->opa[val_act];
|
||||
|
||||
pos -= px_size;
|
||||
if(pos < 0) {
|
||||
pos = 8 - px_size;
|
||||
data_tmp++;
|
||||
}
|
||||
}
|
||||
lv_mem_buf_release(fs_buf);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
274
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_img_decoder.h
Normal file
274
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/lv_img_decoder.h
Normal file
@@ -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 <stdint.h>
|
||||
#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_drv_register()`)
|
||||
* 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 decoders one by one. Once one is able to open the image that decoder is saved in `dsc`
|
||||
* @param dsc describes 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_drv_register())`)
|
||||
* 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*/
|
||||
@@ -0,0 +1,9 @@
|
||||
CSRCS += lv_gpu_nxp.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp"
|
||||
|
||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp/lv_draw_nxp_pxp.mk
|
||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite/lv_draw_nxp_vglite.mk
|
||||
418
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/nxp/lv_gpu_nxp.c
Normal file
418
TSM_PicoW_Sensor/McuLib/LittlevGL/lvgl/src/draw/nxp/lv_gpu_nxp.c
Normal file
@@ -0,0 +1,418 @@
|
||||
/**
|
||||
* @file lv_gpu_nxp.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2022 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_gpu_nxp.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE
|
||||
|
||||
/*
|
||||
* allow to use both PXP and VGLITE
|
||||
|
||||
* both 2D accelerators can be used at the same time:
|
||||
* thus VGLITE can be used to accelerate widget drawing
|
||||
* while PXP accelerates Blit & Fill operations.
|
||||
*/
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
#include "pxp/lv_draw_pxp_blend.h"
|
||||
#endif
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
#include "vglite/lv_draw_vglite_blend.h"
|
||||
#include "vglite/lv_draw_vglite_rect.h"
|
||||
#include "vglite/lv_draw_vglite_arc.h"
|
||||
#endif
|
||||
|
||||
#if LV_COLOR_DEPTH != 32
|
||||
#include "../../core/lv_refr.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void lv_draw_nxp_img_decoded(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 cf);
|
||||
|
||||
static void lv_draw_nxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
|
||||
|
||||
static void lv_draw_nxp_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
static lv_res_t draw_nxp_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
static void lv_draw_nxp_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);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_nxp_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
lv_draw_sw_init_ctx(drv, draw_ctx);
|
||||
|
||||
lv_draw_nxp_ctx_t * nxp_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
|
||||
|
||||
nxp_draw_ctx->base_draw.draw_arc = lv_draw_nxp_arc;
|
||||
nxp_draw_ctx->base_draw.draw_rect = lv_draw_nxp_rect;
|
||||
nxp_draw_ctx->base_draw.draw_img_decoded = lv_draw_nxp_img_decoded;
|
||||
nxp_draw_ctx->blend = lv_draw_nxp_blend;
|
||||
//nxp_draw_ctx->base_draw.wait_for_finish = lv_draw_nxp_wait_cb;
|
||||
}
|
||||
|
||||
void lv_draw_nxp_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
lv_draw_sw_deinit_ctx(drv, draw_ctx);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* During rendering, LVGL might initializes new draw_ctxs and start drawing into
|
||||
* a separate buffer (called layer). If the content to be rendered has "holes",
|
||||
* e.g. rounded corner, LVGL temporarily sets the disp_drv.screen_transp flag.
|
||||
* It means the renderers should draw into an ARGB buffer.
|
||||
* With 32 bit color depth it's not a big problem but with 16 bit color depth
|
||||
* the target pixel format is ARGB8565 which is not supported by the GPU.
|
||||
* In this case, the NXP callbacks should fallback to SW rendering.
|
||||
*/
|
||||
static inline bool need_argb8565_support()
|
||||
{
|
||||
#if LV_COLOR_DEPTH != 32
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
|
||||
if(disp->driver->screen_transp == 1)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void lv_draw_nxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
|
||||
{
|
||||
lv_area_t blend_area;
|
||||
|
||||
/*Let's get the blend area which is the intersection of the area to fill and the clip area.*/
|
||||
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
/*Make the blend area relative to the buffer*/
|
||||
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||
|
||||
bool done = false;
|
||||
|
||||
/*Fill/Blend only non masked, normal blended*/
|
||||
if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && !need_argb8565_support()) {
|
||||
lv_color_t * dest_buf = draw_ctx->buf;
|
||||
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area);
|
||||
lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area);
|
||||
#endif
|
||||
|
||||
const lv_color_t * src_buf = dsc->src_buf;
|
||||
|
||||
if(src_buf == NULL) {
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
done = (lv_gpu_nxp_pxp_fill(dest_buf, dest_stride, &blend_area,
|
||||
dsc->color, dsc->opa) == LV_RES_OK);
|
||||
if(!done)
|
||||
PXP_LOG_TRACE("PXP fill failed. Fallback.");
|
||||
|
||||
#endif
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
if(!done) {
|
||||
done = (lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &blend_area,
|
||||
dsc->color, dsc->opa) == LV_RES_OK);
|
||||
if(!done)
|
||||
VG_LITE_LOG_TRACE("VG-Lite fill failed. Fallback.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
done = (lv_gpu_nxp_pxp_blit(dest_buf, &blend_area, dest_stride, src_buf, dsc->blend_area,
|
||||
dsc->opa, LV_DISP_ROT_NONE) == LV_RES_OK);
|
||||
if(!done)
|
||||
PXP_LOG_TRACE("PXP blit failed. Fallback.");
|
||||
#endif
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
if(!done) {
|
||||
lv_gpu_nxp_vglite_blit_info_t blit;
|
||||
lv_coord_t src_stride = lv_area_get_width(dsc->blend_area);
|
||||
|
||||
blit.src = src_buf;
|
||||
blit.src_width = lv_area_get_width(dsc->blend_area);
|
||||
blit.src_height = lv_area_get_height(dsc->blend_area);
|
||||
blit.src_stride = src_stride * (int32_t)sizeof(lv_color_t);
|
||||
blit.src_area.x1 = (blend_area.x1 - (dsc->blend_area->x1 - draw_ctx->buf_area->x1));
|
||||
blit.src_area.y1 = (blend_area.y1 - (dsc->blend_area->y1 - draw_ctx->buf_area->y1));
|
||||
blit.src_area.x2 = blit.src_area.x1 + blit.src_width - 1;
|
||||
blit.src_area.y2 = blit.src_area.y1 + blit.src_height - 1;
|
||||
|
||||
blit.dst = dest_buf;
|
||||
blit.dst_width = dest_width;
|
||||
blit.dst_height = dest_height;
|
||||
blit.dst_stride = dest_stride * (int32_t)sizeof(lv_color_t);
|
||||
blit.dst_area.x1 = blend_area.x1;
|
||||
blit.dst_area.y1 = blend_area.y1;
|
||||
blit.dst_area.x2 = blend_area.x2;
|
||||
blit.dst_area.y2 = blend_area.y2;
|
||||
|
||||
blit.opa = dsc->opa;
|
||||
blit.zoom = LV_IMG_ZOOM_NONE;
|
||||
blit.angle = 0;
|
||||
|
||||
done = (lv_gpu_nxp_vglite_blit(&blit) == LV_RES_OK);
|
||||
|
||||
if(!done)
|
||||
VG_LITE_LOG_TRACE("VG-Lite blit failed. Fallback.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if(!done)
|
||||
lv_draw_sw_blend_basic(draw_ctx, dsc);
|
||||
}
|
||||
|
||||
static void lv_draw_nxp_img_decoded(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 cf)
|
||||
{
|
||||
/*Use the clip area as draw area*/
|
||||
lv_area_t draw_area;
|
||||
lv_area_copy(&draw_area, draw_ctx->clip_area);
|
||||
bool mask_any = lv_draw_mask_is_any(&draw_area);
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
|
||||
#endif
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
bool scale = (dsc->zoom != LV_IMG_ZOOM_NONE);
|
||||
#endif
|
||||
bool done = false;
|
||||
|
||||
lv_area_t blend_area;
|
||||
/*Let's get the blend area which is the intersection of the area to fill and the clip area.*/
|
||||
if(!_lv_area_intersect(&blend_area, coords, draw_ctx->clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
/*Make the blend area relative to the buffer*/
|
||||
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||
|
||||
const lv_color_t * src_buf = (const lv_color_t *)map_p;
|
||||
if(!src_buf) {
|
||||
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_color_t * dest_buf = draw_ctx->buf;
|
||||
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
if(!mask_any && !scale && !need_argb8565_support()
|
||||
#if LV_COLOR_DEPTH!=32
|
||||
&& !lv_img_cf_has_alpha(cf)
|
||||
#endif
|
||||
) {
|
||||
done = (lv_gpu_nxp_pxp_blit_transform(dest_buf, &blend_area, dest_stride, src_buf, coords,
|
||||
dsc, cf) == LV_RES_OK);
|
||||
if(!done)
|
||||
PXP_LOG_TRACE("PXP blit transform failed. Fallback.");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
if(!done && !mask_any && !need_argb8565_support() &&
|
||||
!lv_img_cf_is_chroma_keyed(cf) && !recolor
|
||||
#if LV_COLOR_DEPTH!=32
|
||||
&& !lv_img_cf_has_alpha(cf)
|
||||
#endif
|
||||
) {
|
||||
lv_gpu_nxp_vglite_blit_info_t blit;
|
||||
lv_coord_t src_stride = lv_area_get_width(coords);
|
||||
|
||||
blit.src = src_buf;
|
||||
blit.src_width = lv_area_get_width(coords);
|
||||
blit.src_height = lv_area_get_height(coords);
|
||||
blit.src_stride = src_stride * (int32_t)sizeof(lv_color_t);
|
||||
blit.src_area.x1 = (blend_area.x1 - (coords->x1 - draw_ctx->buf_area->x1));
|
||||
blit.src_area.y1 = (blend_area.y1 - (coords->y1 - draw_ctx->buf_area->y1));
|
||||
blit.src_area.x2 = blit.src_area.x1 + blit.src_width - 1;
|
||||
blit.src_area.y2 = blit.src_area.y1 + blit.src_height - 1;
|
||||
|
||||
blit.dst = dest_buf;
|
||||
blit.dst_width = lv_area_get_width(draw_ctx->buf_area);
|
||||
blit.dst_height = lv_area_get_height(draw_ctx->buf_area);
|
||||
blit.dst_stride = dest_stride * (int32_t)sizeof(lv_color_t);
|
||||
blit.dst_area.x1 = blend_area.x1;
|
||||
blit.dst_area.y1 = blend_area.y1;
|
||||
blit.dst_area.x2 = blend_area.x2;
|
||||
blit.dst_area.y2 = blend_area.y2;
|
||||
|
||||
blit.opa = dsc->opa;
|
||||
blit.angle = dsc->angle;
|
||||
blit.pivot = dsc->pivot;
|
||||
blit.zoom = dsc->zoom;
|
||||
|
||||
done = (lv_gpu_nxp_vglite_blit_transform(&blit) == LV_RES_OK);
|
||||
|
||||
if(!done)
|
||||
VG_LITE_LOG_TRACE("VG-Lite blit transform failed. Fallback.");
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!done)
|
||||
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
|
||||
}
|
||||
|
||||
static void lv_draw_nxp_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
bool done = false;
|
||||
lv_draw_rect_dsc_t nxp_dsc;
|
||||
|
||||
lv_memcpy(&nxp_dsc, dsc, sizeof(nxp_dsc));
|
||||
#if LV_DRAW_COMPLEX
|
||||
/* Draw only the shadow */
|
||||
nxp_dsc.bg_opa = 0;
|
||||
nxp_dsc.bg_img_opa = 0;
|
||||
nxp_dsc.border_opa = 0;
|
||||
nxp_dsc.outline_opa = 0;
|
||||
|
||||
lv_draw_sw_rect(draw_ctx, &nxp_dsc, coords);
|
||||
|
||||
/* Draw the background */
|
||||
nxp_dsc.shadow_opa = 0;
|
||||
nxp_dsc.bg_opa = dsc->bg_opa;
|
||||
done = (draw_nxp_bg(draw_ctx, &nxp_dsc, coords) == LV_RES_OK);
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
|
||||
/* Draw the remaining parts */
|
||||
nxp_dsc.shadow_opa = 0;
|
||||
if(done)
|
||||
nxp_dsc.bg_opa = 0;
|
||||
nxp_dsc.bg_img_opa = dsc->bg_img_opa;
|
||||
nxp_dsc.border_opa = dsc->border_opa;
|
||||
nxp_dsc.outline_opa = dsc->outline_opa;
|
||||
|
||||
lv_draw_sw_rect(draw_ctx, &nxp_dsc, coords);
|
||||
}
|
||||
|
||||
static lv_res_t draw_nxp_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
if(dsc->bg_opa <= LV_OPA_MIN)
|
||||
return LV_RES_INV;
|
||||
|
||||
lv_area_t bg_coords;
|
||||
lv_area_copy(&bg_coords, coords);
|
||||
|
||||
/*If the border fully covers make the bg area 1px smaller to avoid artifacts on the corners*/
|
||||
if(dsc->border_width > 1 && dsc->border_opa >= (lv_opa_t)LV_OPA_MAX && dsc->radius != 0) {
|
||||
bg_coords.x1 += (dsc->border_side & LV_BORDER_SIDE_LEFT) ? 1 : 0;
|
||||
bg_coords.y1 += (dsc->border_side & LV_BORDER_SIDE_TOP) ? 1 : 0;
|
||||
bg_coords.x2 -= (dsc->border_side & LV_BORDER_SIDE_RIGHT) ? 1 : 0;
|
||||
bg_coords.y2 -= (dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? 1 : 0;
|
||||
}
|
||||
|
||||
lv_area_t clipped_coords;
|
||||
if(!_lv_area_intersect(&clipped_coords, &bg_coords, draw_ctx->clip_area))
|
||||
return LV_RES_INV;
|
||||
|
||||
lv_grad_dir_t grad_dir = dsc->bg_grad.dir;
|
||||
lv_color_t bg_color = grad_dir == LV_GRAD_DIR_NONE ? dsc->bg_color : dsc->bg_grad.stops[0].color;
|
||||
if(bg_color.full == dsc->bg_grad.stops[1].color.full) grad_dir = LV_GRAD_DIR_NONE;
|
||||
|
||||
bool mask_any = lv_draw_mask_is_any(&bg_coords);
|
||||
|
||||
/*
|
||||
* Most simple case: just a plain rectangle (no mask, no radius, no gradient)
|
||||
* shall fallback to lv_draw_sw_blend().
|
||||
*
|
||||
* Complex case: gradient or radius but no mask.
|
||||
*/
|
||||
if(!mask_any && ((dsc->radius != 0) || (grad_dir != LV_GRAD_DIR_NONE)) && !need_argb8565_support()) {
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
lv_res_t res = lv_gpu_nxp_vglite_draw_bg(draw_ctx, dsc, &bg_coords);
|
||||
if(res != LV_RES_OK)
|
||||
VG_LITE_LOG_TRACE("VG-Lite draw bg failed. Fallback.");
|
||||
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
static void lv_draw_nxp_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)
|
||||
{
|
||||
bool done = false;
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(dsc->opa <= LV_OPA_MIN)
|
||||
return;
|
||||
if(dsc->width == 0)
|
||||
return;
|
||||
if(start_angle == end_angle)
|
||||
return;
|
||||
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
if(!need_argb8565_support()) {
|
||||
done = (lv_gpu_nxp_vglite_draw_arc(draw_ctx, dsc, center, (int32_t)radius,
|
||||
(int32_t)start_angle, (int32_t)end_angle) == LV_RES_OK);
|
||||
if(!done)
|
||||
VG_LITE_LOG_TRACE("VG-Lite draw arc failed. Fallback.");
|
||||
}
|
||||
#endif
|
||||
#endif/*LV_DRAW_COMPLEX*/
|
||||
|
||||
if(!done)
|
||||
lv_draw_sw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE*/
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @file lv_gpu_nxp.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2022 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_GPU_NXP_H
|
||||
#define LV_GPU_NXP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE
|
||||
#include "../sw/lv_draw_sw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef lv_draw_sw_ctx_t lv_draw_nxp_ctx_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_nxp_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
void lv_draw_nxp_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#endif /*LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GPU_NXP_H*/
|
||||
@@ -0,0 +1,8 @@
|
||||
CSRCS += lv_draw_pxp_blend.c
|
||||
CSRCS += lv_gpu_nxp_pxp_osa.c
|
||||
CSRCS += lv_gpu_nxp_pxp.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp"
|
||||
@@ -0,0 +1,632 @@
|
||||
/**
|
||||
* @file lv_draw_pxp_blend.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2020-2022 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_pxp_blend.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if LV_COLOR_16_SWAP
|
||||
#error Color swap not implemented. Disable LV_COLOR_16_SWAP feature.
|
||||
#endif
|
||||
|
||||
#if LV_COLOR_DEPTH==16
|
||||
#define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatRGB565
|
||||
#define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatRGB565
|
||||
#define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB565
|
||||
#elif LV_COLOR_DEPTH==32
|
||||
#define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatARGB8888
|
||||
#define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatARGB8888
|
||||
#define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB888
|
||||
#elif
|
||||
#error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32.
|
||||
#endif
|
||||
|
||||
#if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) \
|
||||
|| defined (_WIN64) || defined (__LP64__) || defined (__LLP64__)
|
||||
#define ALIGN_SIZE 8
|
||||
#else
|
||||
#define ALIGN_SIZE 4
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
|
||||
* with combination of transformation (rotation, scale, recolor) and opacity, alpha channel
|
||||
* or color keying. This requires two steps. First step is used for transformation into
|
||||
* a temporary buffer and the second one will handle the color format or opacity.
|
||||
*
|
||||
* @param[in/out] dest_buf destination buffer
|
||||
* @param[in] dest_area area to be copied from src_buf to dst_buf
|
||||
* @param[in] dest_stride width (stride) of destination buffer in pixels
|
||||
* @param[in] src_buf source buffer
|
||||
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
|
||||
* @param[in] dsc image descriptor
|
||||
* @param[in] cf color format
|
||||
* @retval LV_RES_OK Fill completed
|
||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
|
||||
*/
|
||||
static lv_res_t lv_gpu_nxp_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, const lv_area_t * src_area,
|
||||
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
|
||||
|
||||
/**
|
||||
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
|
||||
* with transformation and full opacity.
|
||||
*
|
||||
* @param[in/out] dest_buf destination buffer
|
||||
* @param[in] dest_area area to be copied from src_buf to dst_buf
|
||||
* @param[in] dest_stride width (stride) of destination buffer in pixels
|
||||
* @param[in] src_buf source buffer
|
||||
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
|
||||
* @param[in] dsc image descriptor
|
||||
* @param[in] cf color format
|
||||
* @retval LV_RES_OK Fill completed
|
||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
|
||||
*/
|
||||
static lv_res_t lv_gpu_nxp_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t * dest_area,
|
||||
lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, const lv_area_t * src_area,
|
||||
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
|
||||
|
||||
/**
|
||||
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
|
||||
* without transformation but handling color format or opacity.
|
||||
*
|
||||
* @param[in/out] dest_buf destination buffer
|
||||
* @param[in] dest_area area to be copied from src_buf to dst_buf
|
||||
* @param[in] dest_stride width (stride) of destination buffer in pixels
|
||||
* @param[in] src_buf source buffer
|
||||
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
|
||||
* @param[in] dsc image descriptor
|
||||
* @param[in] cf color format
|
||||
* @retval LV_RES_OK Fill completed
|
||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
|
||||
*/
|
||||
static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area,
|
||||
lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, const lv_area_t * src_area,
|
||||
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#define ROUND_UP(x, align) ((x + (align - 1)) & ~(align - 1))
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_res_t lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area,
|
||||
lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
uint32_t area_size = lv_area_get_size(fill_area);
|
||||
lv_coord_t area_w = lv_area_get_width(fill_area);
|
||||
lv_coord_t area_h = lv_area_get_height(fill_area);
|
||||
|
||||
if(opa >= (lv_opa_t)LV_OPA_MAX) {
|
||||
if(area_size < LV_GPU_NXP_PXP_FILL_SIZE_LIMIT) {
|
||||
PXP_LOG_TRACE("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_PXP_FILL_SIZE_LIMIT);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(area_size < LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT) {
|
||||
PXP_LOG_TRACE("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
PXP_Init(LV_GPU_NXP_PXP_ID);
|
||||
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
||||
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/
|
||||
|
||||
/*OUT buffer configure*/
|
||||
pxp_output_buffer_config_t outputConfig = {
|
||||
.pixelFormat = PXP_OUT_PIXEL_FORMAT,
|
||||
.interlacedMode = kPXP_OutputProgressive,
|
||||
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * fill_area->y1 + fill_area->x1),
|
||||
.buffer1Addr = (uint32_t)NULL,
|
||||
.pitchBytes = dest_stride * sizeof(lv_color_t),
|
||||
.width = area_w,
|
||||
.height = area_h
|
||||
};
|
||||
|
||||
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputConfig);
|
||||
|
||||
if(opa >= (lv_opa_t)LV_OPA_MAX) {
|
||||
/*Simple color fill without opacity - AS disabled*/
|
||||
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||
|
||||
}
|
||||
else {
|
||||
/*Fill with opacity - AS used as source (same as OUT)*/
|
||||
pxp_as_buffer_config_t asBufferConfig = {
|
||||
.pixelFormat = PXP_AS_PIXEL_FORMAT,
|
||||
.bufferAddr = (uint32_t)outputConfig.buffer0Addr,
|
||||
.pitchBytes = outputConfig.pitchBytes
|
||||
};
|
||||
|
||||
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
||||
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, area_w, area_h);
|
||||
}
|
||||
|
||||
/*Disable PS, use as color generator*/
|
||||
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||
PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(color));
|
||||
|
||||
/**
|
||||
* Configure Porter-Duff blending - src settings are unused for fill without opacity (opa = 0xff).
|
||||
*
|
||||
* Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h:
|
||||
* srcFactorMode is actually applied on PS alpha value
|
||||
* dstFactorMode is actually applied on AS alpha value
|
||||
*/
|
||||
pxp_porter_duff_config_t pdConfig = {
|
||||
.enable = 1,
|
||||
.dstColorMode = kPXP_PorterDuffColorNoAlpha,
|
||||
.srcColorMode = kPXP_PorterDuffColorNoAlpha,
|
||||
.dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha,
|
||||
.srcGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha,
|
||||
.dstFactorMode = kPXP_PorterDuffFactorStraight,
|
||||
.srcFactorMode = (opa >= (lv_opa_t)LV_OPA_MAX) ? kPXP_PorterDuffFactorStraight : kPXP_PorterDuffFactorInversed,
|
||||
.dstGlobalAlpha = opa,
|
||||
.srcGlobalAlpha = opa,
|
||||
.dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/
|
||||
.srcAlphaMode = kPXP_PorterDuffAlphaStraight /*don't care*/
|
||||
};
|
||||
|
||||
PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig);
|
||||
|
||||
lv_gpu_nxp_pxp_run(); /*Start PXP task*/
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
lv_res_t lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, const lv_area_t * src_area, lv_opa_t opa, lv_disp_rot_t angle)
|
||||
{
|
||||
uint32_t dest_size = lv_area_get_size(dest_area);
|
||||
lv_coord_t dest_w = lv_area_get_width(dest_area);
|
||||
lv_coord_t dest_h = lv_area_get_height(dest_area);
|
||||
|
||||
if(opa >= (lv_opa_t)LV_OPA_MAX) {
|
||||
if(dest_size < LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT) {
|
||||
PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(dest_size < LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT) {
|
||||
PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
PXP_Init(LV_GPU_NXP_PXP_ID);
|
||||
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
||||
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*block size 16x16 for higher performance*/
|
||||
|
||||
/* convert rotation angle */
|
||||
pxp_rotate_degree_t pxp_rot;
|
||||
switch(angle) {
|
||||
case LV_DISP_ROT_NONE:
|
||||
pxp_rot = kPXP_Rotate0;
|
||||
break;
|
||||
case LV_DISP_ROT_90:
|
||||
pxp_rot = kPXP_Rotate90;
|
||||
break;
|
||||
case LV_DISP_ROT_180:
|
||||
pxp_rot = kPXP_Rotate180;
|
||||
break;
|
||||
case LV_DISP_ROT_270:
|
||||
pxp_rot = kPXP_Rotate270;
|
||||
break;
|
||||
default:
|
||||
pxp_rot = kPXP_Rotate0;
|
||||
break;
|
||||
}
|
||||
PXP_SetRotateConfig(LV_GPU_NXP_PXP_ID, kPXP_RotateOutputBuffer, pxp_rot, kPXP_FlipDisable);
|
||||
|
||||
pxp_as_blend_config_t asBlendConfig = {
|
||||
.alpha = opa,
|
||||
.invertAlpha = false,
|
||||
.alphaMode = kPXP_AlphaRop,
|
||||
.ropMode = kPXP_RopMergeAs
|
||||
};
|
||||
|
||||
if(opa >= (lv_opa_t)LV_OPA_MAX) {
|
||||
/*Simple blit, no effect - Disable PS buffer*/
|
||||
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||
}
|
||||
else {
|
||||
pxp_ps_buffer_config_t psBufferConfig = {
|
||||
.pixelFormat = PXP_PS_PIXEL_FORMAT,
|
||||
.swapByte = false,
|
||||
.bufferAddr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1),
|
||||
.bufferAddrU = 0U,
|
||||
.bufferAddrV = 0U,
|
||||
.pitchBytes = dest_stride * sizeof(lv_color_t)
|
||||
};
|
||||
|
||||
asBlendConfig.alphaMode = kPXP_AlphaOverride;
|
||||
|
||||
PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig);
|
||||
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1, dest_h - 1);
|
||||
}
|
||||
|
||||
lv_coord_t src_stride = lv_area_get_width(src_area);
|
||||
|
||||
/*AS buffer - source image*/
|
||||
pxp_as_buffer_config_t asBufferConfig = {
|
||||
.pixelFormat = PXP_AS_PIXEL_FORMAT,
|
||||
.bufferAddr = (uint32_t)src_buf,
|
||||
.pitchBytes = src_stride * sizeof(lv_color_t)
|
||||
};
|
||||
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
||||
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
|
||||
PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig);
|
||||
PXP_EnableAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, false);
|
||||
|
||||
/*Output buffer.*/
|
||||
pxp_output_buffer_config_t outputBufferConfig = {
|
||||
.pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT,
|
||||
.interlacedMode = kPXP_OutputProgressive,
|
||||
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1),
|
||||
.buffer1Addr = (uint32_t)0U,
|
||||
.pitchBytes = dest_stride * sizeof(lv_color_t),
|
||||
.width = dest_w,
|
||||
.height = dest_h
|
||||
};
|
||||
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
|
||||
|
||||
lv_gpu_nxp_pxp_run(); /* Start PXP task */
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
lv_res_t lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, const lv_area_t * src_area,
|
||||
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
|
||||
{
|
||||
uint32_t dest_size = lv_area_get_size(dest_area);
|
||||
|
||||
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) {
|
||||
if(dest_size < LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT) {
|
||||
PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(dest_size < LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT) {
|
||||
PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
|
||||
bool rotation = (dsc->angle != 0);
|
||||
|
||||
if(rotation) {
|
||||
if(dsc->angle != 0 && dsc->angle != 900 && dsc->angle != 1800 && dsc->angle != 2700) {
|
||||
PXP_LOG_TRACE("Rotation angle %d is not supported. PXP can rotate only 90x angle.", dsc->angle);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
if(recolor || rotation) {
|
||||
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX && !lv_img_cf_has_alpha(cf) && !lv_img_cf_is_chroma_keyed(cf))
|
||||
return lv_gpu_nxp_pxp_blit_cover(dest_buf, dest_area, dest_stride, src_buf, src_area, dsc, cf);
|
||||
else
|
||||
/*Recolor and/or rotation with alpha or opacity is done in two steps.*/
|
||||
return lv_gpu_nxp_pxp_blit_opa(dest_buf, dest_area, dest_stride, src_buf, src_area, dsc, cf);
|
||||
}
|
||||
|
||||
return lv_gpu_nxp_pxp_blit_cf(dest_buf, dest_area, dest_stride, src_buf, src_area, dsc, cf);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_res_t lv_gpu_nxp_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, const lv_area_t * src_area,
|
||||
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
|
||||
{
|
||||
lv_coord_t dest_w = lv_area_get_width(dest_area);
|
||||
lv_coord_t dest_h = lv_area_get_height(dest_area);
|
||||
lv_res_t res;
|
||||
uint32_t size = dest_w * dest_h * sizeof(lv_color_t);
|
||||
|
||||
if(ROUND_UP(size, ALIGN_SIZE) >= LV_MEM_SIZE)
|
||||
PXP_RETURN_INV("Insufficient memory for temporary buffer. Please increase LV_MEM_SIZE.");
|
||||
|
||||
lv_color_t * tmp_buf = (lv_color_t *)lv_mem_buf_get(size);
|
||||
if(!tmp_buf)
|
||||
PXP_RETURN_INV("Allocating temporary buffer failed.");
|
||||
|
||||
const lv_area_t tmp_area = {
|
||||
.x1 = 0,
|
||||
.y1 = 0,
|
||||
.x2 = dest_w - 1,
|
||||
.y2 = dest_h - 1
|
||||
};
|
||||
|
||||
/*Step 1: Transform with full opacity to temporary buffer*/
|
||||
res = lv_gpu_nxp_pxp_blit_cover(tmp_buf, &tmp_area, dest_w, src_buf, src_area, dsc, cf);
|
||||
if(res != LV_RES_OK) {
|
||||
PXP_LOG_TRACE("Blit cover with full opacity failed.");
|
||||
lv_mem_buf_release(tmp_buf);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*Step 2: Blit temporary results with required opacity to output*/
|
||||
res = lv_gpu_nxp_pxp_blit_cf(dest_buf, dest_area, dest_stride, tmp_buf, &tmp_area, dsc, cf);
|
||||
|
||||
/*Clean-up memory*/
|
||||
lv_mem_buf_release(tmp_buf);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static lv_res_t lv_gpu_nxp_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t * dest_area,
|
||||
lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, const lv_area_t * src_area,
|
||||
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
|
||||
{
|
||||
lv_coord_t dest_w = lv_area_get_width(dest_area);
|
||||
lv_coord_t dest_h = lv_area_get_height(dest_area);
|
||||
|
||||
bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
|
||||
bool rotation = (dsc->angle != 0);
|
||||
|
||||
PXP_Init(LV_GPU_NXP_PXP_ID);
|
||||
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
||||
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*block size 16x16 for higher performance*/
|
||||
|
||||
if(rotation) {
|
||||
/*
|
||||
* PXP is set to process 16x16 blocks to optimize the system for memory
|
||||
* bandwidth and image processing time.
|
||||
* The output engine essentially truncates any output pixels after the
|
||||
* desired number of pixels has been written.
|
||||
* When rotating a source image and the output is not divisible by the block
|
||||
* size, the incorrect pixels could be truncated and the final output image
|
||||
* can look shifted.
|
||||
*/
|
||||
if(lv_area_get_width(src_area) % 16 || lv_area_get_height(src_area) % 16) {
|
||||
PXP_LOG_TRACE("Rotation is not supported for image w/o alignment to block size 16x16.");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
/*Convert rotation angle*/
|
||||
pxp_rotate_degree_t pxp_rot;
|
||||
switch(dsc->angle) {
|
||||
case 0:
|
||||
pxp_rot = kPXP_Rotate0;
|
||||
break;
|
||||
case 900:
|
||||
pxp_rot = kPXP_Rotate90;
|
||||
break;
|
||||
case 1800:
|
||||
pxp_rot = kPXP_Rotate180;
|
||||
break;
|
||||
case 2700:
|
||||
pxp_rot = kPXP_Rotate270;
|
||||
break;
|
||||
default:
|
||||
PXP_LOG_TRACE("Rotation angle %d is not supported. PXP can rotate only 90x angle.", dsc->angle);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
PXP_SetRotateConfig(LV_GPU_NXP_PXP_ID, kPXP_RotateOutputBuffer, pxp_rot, kPXP_FlipDisable);
|
||||
}
|
||||
|
||||
lv_coord_t src_stride = lv_area_get_width(src_area);
|
||||
|
||||
/*AS buffer - source image*/
|
||||
pxp_as_buffer_config_t asBufferConfig = {
|
||||
.pixelFormat = PXP_AS_PIXEL_FORMAT,
|
||||
.bufferAddr = (uint32_t)src_buf,
|
||||
.pitchBytes = src_stride * sizeof(lv_color_t)
|
||||
};
|
||||
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
||||
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
|
||||
|
||||
/*Disable PS buffer*/
|
||||
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||
if(recolor)
|
||||
/*Use as color generator*/
|
||||
PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(dsc->recolor));
|
||||
|
||||
/*Output buffer*/
|
||||
pxp_output_buffer_config_t outputBufferConfig = {
|
||||
.pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT,
|
||||
.interlacedMode = kPXP_OutputProgressive,
|
||||
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1),
|
||||
.buffer1Addr = (uint32_t)0U,
|
||||
.pitchBytes = dest_stride * sizeof(lv_color_t),
|
||||
.width = dest_w,
|
||||
.height = dest_h
|
||||
};
|
||||
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
|
||||
|
||||
if(recolor || lv_img_cf_has_alpha(cf)) {
|
||||
/**
|
||||
* Configure Porter-Duff blending.
|
||||
*
|
||||
* Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h:
|
||||
* srcFactorMode is actually applied on PS alpha value
|
||||
* dstFactorMode is actually applied on AS alpha value
|
||||
*/
|
||||
pxp_porter_duff_config_t pdConfig = {
|
||||
.enable = 1,
|
||||
.dstColorMode = kPXP_PorterDuffColorWithAlpha,
|
||||
.srcColorMode = kPXP_PorterDuffColorNoAlpha,
|
||||
.dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha,
|
||||
.srcGlobalAlphaMode = lv_img_cf_has_alpha(cf) ? kPXP_PorterDuffLocalAlpha : kPXP_PorterDuffGlobalAlpha,
|
||||
.dstFactorMode = kPXP_PorterDuffFactorStraight,
|
||||
.srcFactorMode = kPXP_PorterDuffFactorInversed,
|
||||
.dstGlobalAlpha = recolor ? dsc->recolor_opa : 0x00,
|
||||
.srcGlobalAlpha = 0xff,
|
||||
.dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/
|
||||
.srcAlphaMode = kPXP_PorterDuffAlphaStraight
|
||||
};
|
||||
PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig);
|
||||
}
|
||||
|
||||
lv_gpu_nxp_pxp_run(); /*Start PXP task*/
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area,
|
||||
lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, const lv_area_t * src_area,
|
||||
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
|
||||
{
|
||||
lv_coord_t dest_w = lv_area_get_width(dest_area);
|
||||
lv_coord_t dest_h = lv_area_get_height(dest_area);
|
||||
|
||||
PXP_Init(LV_GPU_NXP_PXP_ID);
|
||||
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
||||
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*block size 16x16 for higher performance*/
|
||||
|
||||
pxp_as_blend_config_t asBlendConfig = {
|
||||
.alpha = dsc->opa,
|
||||
.invertAlpha = false,
|
||||
.alphaMode = kPXP_AlphaRop,
|
||||
.ropMode = kPXP_RopMergeAs
|
||||
};
|
||||
|
||||
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX && !lv_img_cf_is_chroma_keyed(cf) && !lv_img_cf_has_alpha(cf)) {
|
||||
/*Simple blit, no effect - Disable PS buffer*/
|
||||
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||
}
|
||||
else {
|
||||
/*PS must be enabled to fetch background pixels.
|
||||
PS and OUT buffers are the same, blend will be done in-place*/
|
||||
pxp_ps_buffer_config_t psBufferConfig = {
|
||||
.pixelFormat = PXP_PS_PIXEL_FORMAT,
|
||||
.swapByte = false,
|
||||
.bufferAddr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1),
|
||||
.bufferAddrU = 0U,
|
||||
.bufferAddrV = 0U,
|
||||
.pitchBytes = dest_stride * sizeof(lv_color_t)
|
||||
};
|
||||
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) {
|
||||
asBlendConfig.alphaMode = lv_img_cf_has_alpha(cf) ? kPXP_AlphaEmbedded : kPXP_AlphaOverride;
|
||||
}
|
||||
else {
|
||||
asBlendConfig.alphaMode = lv_img_cf_has_alpha(cf) ? kPXP_AlphaMultiply : kPXP_AlphaOverride;
|
||||
}
|
||||
PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig);
|
||||
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1, dest_h - 1);
|
||||
}
|
||||
|
||||
lv_coord_t src_stride = lv_area_get_width(src_area);
|
||||
|
||||
/*AS buffer - source image*/
|
||||
pxp_as_buffer_config_t asBufferConfig = {
|
||||
.pixelFormat = PXP_AS_PIXEL_FORMAT,
|
||||
.bufferAddr = (uint32_t)src_buf,
|
||||
.pitchBytes = src_stride * sizeof(lv_color_t)
|
||||
};
|
||||
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
||||
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
|
||||
PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig);
|
||||
|
||||
if(lv_img_cf_is_chroma_keyed(cf)) {
|
||||
lv_color_t colorKeyLow = LV_COLOR_CHROMA_KEY;
|
||||
lv_color_t colorKeyHigh = LV_COLOR_CHROMA_KEY;
|
||||
|
||||
bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
|
||||
|
||||
if(recolor) {
|
||||
/* New color key after recoloring */
|
||||
lv_color_t colorKey = lv_color_mix(dsc->recolor, LV_COLOR_CHROMA_KEY, dsc->recolor_opa);
|
||||
|
||||
LV_COLOR_SET_R(colorKeyLow, colorKey.ch.red != 0 ? colorKey.ch.red - 1 : 0);
|
||||
LV_COLOR_SET_G(colorKeyLow, colorKey.ch.green != 0 ? colorKey.ch.green - 1 : 0);
|
||||
LV_COLOR_SET_B(colorKeyLow, colorKey.ch.blue != 0 ? colorKey.ch.blue - 1 : 0);
|
||||
|
||||
#if LV_COLOR_DEPTH==16
|
||||
LV_COLOR_SET_R(colorKeyHigh, colorKey.ch.red != 0x1f ? colorKey.ch.red + 1 : 0x1f);
|
||||
LV_COLOR_SET_G(colorKeyHigh, colorKey.ch.green != 0x3f ? colorKey.ch.green + 1 : 0x3f);
|
||||
LV_COLOR_SET_B(colorKeyHigh, colorKey.ch.blue != 0x1f ? colorKey.ch.blue + 1 : 0x1f);
|
||||
#else /*LV_COLOR_DEPTH==32*/
|
||||
LV_COLOR_SET_R(colorKeyHigh, colorKey.ch.red != 0xff ? colorKey.ch.red + 1 : 0xff);
|
||||
LV_COLOR_SET_G(colorKeyHigh, colorKey.ch.green != 0xff ? colorKey.ch.green + 1 : 0xff);
|
||||
LV_COLOR_SET_B(colorKeyHigh, colorKey.ch.blue != 0xff ? colorKey.ch.blue + 1 : 0xff);
|
||||
#endif
|
||||
}
|
||||
|
||||
PXP_SetAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, lv_color_to32(colorKeyLow),
|
||||
lv_color_to32(colorKeyHigh));
|
||||
}
|
||||
|
||||
PXP_EnableAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, lv_img_cf_is_chroma_keyed(cf));
|
||||
|
||||
/*Output buffer.*/
|
||||
pxp_output_buffer_config_t outputBufferConfig = {
|
||||
.pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT,
|
||||
.interlacedMode = kPXP_OutputProgressive,
|
||||
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1),
|
||||
.buffer1Addr = (uint32_t)0U,
|
||||
.pitchBytes = dest_stride * sizeof(lv_color_t),
|
||||
.width = dest_w,
|
||||
.height = dest_h
|
||||
};
|
||||
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
|
||||
|
||||
lv_gpu_nxp_pxp_run(); /* Start PXP task */
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_PXP*/
|
||||
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* @file lv_draw_pxp_blend.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2020-2022 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_DRAW_PXP_BLEND_H
|
||||
#define LV_DRAW_PXP_BLEND_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
#include "lv_gpu_nxp_pxp.h"
|
||||
#include "../../sw/lv_draw_sw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#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 5000
|
||||
#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 5000
|
||||
#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 5000
|
||||
#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 5000
|
||||
#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 5000
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Fill area, with optional opacity.
|
||||
*
|
||||
* @param[in/out] dest_buf destination buffer
|
||||
* @param[in] dest_stride 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
|
||||
* @retval LV_RES_OK Fill completed
|
||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
|
||||
*/
|
||||
lv_res_t lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area,
|
||||
lv_color_t color, lv_opa_t opa);
|
||||
|
||||
/**
|
||||
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects.
|
||||
* By default, image is copied directly, with optional opacity. This function can also
|
||||
* rotate the display output buffer to a specified angle (90x step).
|
||||
*
|
||||
* @param[in/out] dest_buf destination buffer
|
||||
* @param[in] dest_area destination area
|
||||
* @param[in] dest_stride width (stride) of destination buffer in pixels
|
||||
* @param[in] src_buf source buffer
|
||||
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
|
||||
* @param[in] opa opacity of the result
|
||||
* @param[in] angle display rotation angle (90x)
|
||||
* @retval LV_RES_OK Fill completed
|
||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
|
||||
*/
|
||||
lv_res_t lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, const lv_area_t * src_area, lv_opa_t opa, lv_disp_rot_t angle);
|
||||
|
||||
/**
|
||||
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with transformation.
|
||||
*
|
||||
*
|
||||
* @param[in/out] dest_buf destination buffer
|
||||
* @param[in] dest_area destination area
|
||||
* @param[in] dest_stride width (stride) of destination buffer in pixels
|
||||
* @param[in] src_buf source buffer
|
||||
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
|
||||
* @param[in] dsc image descriptor
|
||||
* @param[in] cf color format
|
||||
* @retval LV_RES_OK Fill completed
|
||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
|
||||
*/
|
||||
lv_res_t lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, const lv_area_t * src_area, const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_PXP*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_PXP_BLEND_H*/
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* @file lv_gpu_nxp_pxp.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2020-2022 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_gpu_nxp_pxp.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
#include "lv_gpu_nxp_pxp_osa.h"
|
||||
#include "../../../core/lv_refr.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Clean & invalidate cache.
|
||||
*/
|
||||
static void invalidate_cache(void);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
static lv_nxp_pxp_cfg_t * pxp_cfg;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_res_t lv_gpu_nxp_pxp_init(void)
|
||||
{
|
||||
pxp_cfg = lv_gpu_nxp_pxp_get_cfg();
|
||||
|
||||
if(!pxp_cfg || !pxp_cfg->pxp_interrupt_deinit || !pxp_cfg->pxp_interrupt_init || !pxp_cfg->pxp_run)
|
||||
PXP_RETURN_INV("PXP configuration error.");
|
||||
|
||||
PXP_Init(LV_GPU_NXP_PXP_ID);
|
||||
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
||||
PXP_EnableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable);
|
||||
|
||||
if(pxp_cfg->pxp_interrupt_init() != LV_RES_OK) {
|
||||
PXP_Deinit(LV_GPU_NXP_PXP_ID);
|
||||
PXP_RETURN_INV("PXP interrupt init failed.");
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
void lv_gpu_nxp_pxp_deinit(void)
|
||||
{
|
||||
pxp_cfg->pxp_interrupt_deinit();
|
||||
PXP_DisableInterrupts(PXP, kPXP_CompleteInterruptEnable);
|
||||
PXP_Deinit(LV_GPU_NXP_PXP_ID);
|
||||
}
|
||||
|
||||
void lv_gpu_nxp_pxp_run(void)
|
||||
{
|
||||
/*Clean & invalidate cache*/
|
||||
invalidate_cache();
|
||||
|
||||
pxp_cfg->pxp_run();
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void invalidate_cache(void)
|
||||
{
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
if(disp->driver->clean_dcache_cb)
|
||||
disp->driver->clean_dcache_cb(disp->driver);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_PXP*/
|
||||
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* @file lv_gpu_nxp_pxp.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2020-2022 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_GPU_NXP_PXP_H
|
||||
#define LV_GPU_NXP_PXP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
#include "fsl_cache.h"
|
||||
#include "fsl_pxp.h"
|
||||
|
||||
#include "../../../misc/lv_log.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/** PXP module instance to use*/
|
||||
#define LV_GPU_NXP_PXP_ID PXP
|
||||
|
||||
/** PXP interrupt line ID*/
|
||||
#define LV_GPU_NXP_PXP_IRQ_ID PXP_IRQn
|
||||
|
||||
#ifndef LV_GPU_NXP_PXP_LOG_ERRORS
|
||||
/** Enable logging of PXP errors (\see LV_LOG_ERROR)*/
|
||||
#define LV_GPU_NXP_PXP_LOG_ERRORS 1
|
||||
#endif
|
||||
|
||||
#ifndef LV_GPU_NXP_PXP_LOG_TRACES
|
||||
/** Enable logging of PXP errors (\see LV_LOG_ERROR)*/
|
||||
#define LV_GPU_NXP_PXP_LOG_TRACES 0
|
||||
#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;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Reset and initialize PXP device. This function should be called as a part
|
||||
* of display init sequence.
|
||||
*
|
||||
* @retval LV_RES_OK PXP init completed
|
||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
|
||||
*/
|
||||
lv_res_t lv_gpu_nxp_pxp_init(void);
|
||||
|
||||
/**
|
||||
* Disable PXP device. Should be called during display deinit sequence.
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_deinit(void);
|
||||
|
||||
/**
|
||||
* Start PXP job and wait for completion.
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_run(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#define PXP_COND_STOP(cond, txt) \
|
||||
do { \
|
||||
if (cond) { \
|
||||
LV_LOG_ERROR("%s. STOP!", txt); \
|
||||
for ( ; ; ); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#if LV_GPU_NXP_PXP_LOG_ERRORS
|
||||
#define PXP_RETURN_INV(fmt, ...) \
|
||||
do { \
|
||||
LV_LOG_ERROR(fmt, ##__VA_ARGS__); \
|
||||
return LV_RES_INV; \
|
||||
} while (0)
|
||||
#else
|
||||
#define PXP_RETURN_INV(fmt, ...) \
|
||||
do { \
|
||||
return LV_RES_INV; \
|
||||
}while(0)
|
||||
#endif /*LV_GPU_NXP_PXP_LOG_ERRORS*/
|
||||
|
||||
#if LV_GPU_NXP_PXP_LOG_TRACES
|
||||
#define PXP_LOG_TRACE(fmt, ...) \
|
||||
do { \
|
||||
LV_LOG_ERROR(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define PXP_LOG_TRACE(fmt, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif /*LV_GPU_NXP_PXP_LOG_TRACES*/
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_PXP*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GPU_NXP_PXP_H*/
|
||||
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* @file lv_gpu_nxp_pxp_osa.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2020, 2022 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_gpu_nxp_pxp_osa.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT
|
||||
#include "../../../misc/lv_log.h"
|
||||
#include "fsl_pxp.h"
|
||||
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* PXP interrupt initialization.
|
||||
*/
|
||||
static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void);
|
||||
|
||||
/**
|
||||
* PXP interrupt de-initialization.
|
||||
*/
|
||||
static void _lv_gpu_nxp_pxp_interrupt_deinit(void);
|
||||
|
||||
/**
|
||||
* Start the PXP job and wait for task completion.
|
||||
*/
|
||||
static void _lv_gpu_nxp_pxp_run(void);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
static SemaphoreHandle_t s_pxpIdle;
|
||||
#else
|
||||
static volatile bool s_pxpIdle;
|
||||
#endif
|
||||
|
||||
static lv_nxp_pxp_cfg_t pxp_default_cfg = {
|
||||
.pxp_interrupt_init = _lv_gpu_nxp_pxp_interrupt_init,
|
||||
.pxp_interrupt_deinit = _lv_gpu_nxp_pxp_interrupt_deinit,
|
||||
.pxp_run = _lv_gpu_nxp_pxp_run
|
||||
};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void PXP_IRQHandler(void)
|
||||
{
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
BaseType_t taskAwake = pdFALSE;
|
||||
#endif
|
||||
|
||||
if(kPXP_CompleteFlag & PXP_GetStatusFlags(LV_GPU_NXP_PXP_ID)) {
|
||||
PXP_ClearStatusFlags(LV_GPU_NXP_PXP_ID, kPXP_CompleteFlag);
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
xSemaphoreGiveFromISR(s_pxpIdle, &taskAwake);
|
||||
portYIELD_FROM_ISR(taskAwake);
|
||||
#else
|
||||
s_pxpIdle = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
lv_nxp_pxp_cfg_t * lv_gpu_nxp_pxp_get_cfg(void)
|
||||
{
|
||||
return &pxp_default_cfg;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void)
|
||||
{
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
s_pxpIdle = xSemaphoreCreateBinary();
|
||||
if(s_pxpIdle == NULL)
|
||||
return LV_RES_INV;
|
||||
|
||||
NVIC_SetPriority(LV_GPU_NXP_PXP_IRQ_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);
|
||||
#else
|
||||
s_pxpIdle = true;
|
||||
#endif
|
||||
|
||||
NVIC_EnableIRQ(LV_GPU_NXP_PXP_IRQ_ID);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static void _lv_gpu_nxp_pxp_interrupt_deinit(void)
|
||||
{
|
||||
NVIC_DisableIRQ(LV_GPU_NXP_PXP_IRQ_ID);
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
vSemaphoreDelete(s_pxpIdle);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _lv_gpu_nxp_pxp_run(void)
|
||||
{
|
||||
#if !defined(SDK_OS_FREE_RTOS)
|
||||
s_pxpIdle = false;
|
||||
#endif
|
||||
|
||||
PXP_EnableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable);
|
||||
PXP_Start(LV_GPU_NXP_PXP_ID);
|
||||
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
PXP_COND_STOP(!xSemaphoreTake(s_pxpIdle, portMAX_DELAY), "xSemaphoreTake failed.");
|
||||
#else
|
||||
while(s_pxpIdle == false) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT*/
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @file lv_gpu_nxp_pxp_osa.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2020, 2022 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_GPU_NXP_PXP_OSA_H
|
||||
#define LV_GPU_NXP_PXP_OSA_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT
|
||||
#include "lv_gpu_nxp_pxp.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* PXP device interrupt handler. Used to check PXP task completion status.
|
||||
*/
|
||||
void PXP_IRQHandler(void);
|
||||
|
||||
/**
|
||||
* Helper function to get the PXP default configuration.
|
||||
*/
|
||||
lv_nxp_pxp_cfg_t * lv_gpu_nxp_pxp_get_cfg(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GPU_NXP_PXP_OSA_H*/
|
||||
@@ -0,0 +1,9 @@
|
||||
CSRCS += lv_draw_vglite_arc.c
|
||||
CSRCS += lv_draw_vglite_blend.c
|
||||
CSRCS += lv_draw_vglite_rect.c
|
||||
CSRCS += lv_gpu_nxp_vglite.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite"
|
||||
@@ -0,0 +1,699 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_arc.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2021, 2022 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_vglite_arc.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
#include "math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define T_FRACTION 16384.0f
|
||||
|
||||
#define DICHOTO_ITER 5
|
||||
|
||||
static const uint16_t TperDegree[90] = {
|
||||
0, 174, 348, 522, 697, 873, 1049, 1226, 1403, 1581,
|
||||
1759, 1938, 2117, 2297, 2477, 2658, 2839, 3020, 3202, 3384,
|
||||
3567, 3749, 3933, 4116, 4300, 4484, 4668, 4852, 5037, 5222,
|
||||
5407, 5592, 5777, 5962, 6148, 6334, 6519, 6705, 6891, 7077,
|
||||
7264, 7450, 7636, 7822, 8008, 8193, 8378, 8564, 8750, 8936,
|
||||
9122, 9309, 9495, 9681, 9867, 10052, 10238, 10424, 10609, 10794,
|
||||
10979, 11164, 11349, 11534, 11718, 11902, 12086, 12270, 12453, 12637,
|
||||
12819, 13002, 13184, 13366, 13547, 13728, 13909, 14089, 14269, 14448,
|
||||
14627, 14805, 14983, 15160, 15337, 15513, 15689, 15864, 16038, 16212
|
||||
};
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/* intermediate arc params */
|
||||
typedef struct _vg_arc {
|
||||
int32_t angle; /* angle <90deg */
|
||||
int32_t quarter; /* 0-3 counter-clockwise */
|
||||
int32_t rad; /* radius */
|
||||
int32_t p0x; /* point P0 */
|
||||
int32_t p0y;
|
||||
int32_t p1x; /* point P1 */
|
||||
int32_t p1y;
|
||||
int32_t p2x; /* point P2 */
|
||||
int32_t p2y;
|
||||
int32_t p3x; /* point P3 */
|
||||
int32_t p3y;
|
||||
} vg_arc;
|
||||
|
||||
typedef struct _cubic_cont_pt {
|
||||
float p0;
|
||||
float p1;
|
||||
float p2;
|
||||
float p3;
|
||||
} cubic_cont_pt;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void rotate_point(int32_t angle, int32_t * x, int32_t * y);
|
||||
static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius,
|
||||
int32_t start_angle, int32_t end_angle, lv_point_t center, bool cw);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
||||
int32_t radius, int32_t start_angle, int32_t end_angle)
|
||||
{
|
||||
|
||||
vg_lite_buffer_t vgbuf;
|
||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||
lv_color32_t col32 = {.full = lv_color_to32(dsc->color)}; /*Convert color to RGBA8888*/
|
||||
lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area);
|
||||
lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area);
|
||||
vg_lite_path_t path;
|
||||
vg_lite_color_t vgcol; /* vglite takes ABGR */
|
||||
vg_lite_matrix_t matrix;
|
||||
lv_opa_t opa = dsc->opa;
|
||||
bool donut = ((end_angle - start_angle) % 360 == 0) ? true : false;
|
||||
lv_point_t clip_center = {center->x - draw_ctx->buf_area->x1, center->y - draw_ctx->buf_area->y1};
|
||||
|
||||
/* path: max size = 16 cubic bezier (7 words each) */
|
||||
int32_t arc_path[16 * 7];
|
||||
lv_memset_00(arc_path, sizeof(arc_path));
|
||||
|
||||
/*** Init destination buffer ***/
|
||||
if(lv_vglite_init_buf(&vgbuf, (uint32_t)dest_width, (uint32_t)dest_height, (uint32_t)dest_width * sizeof(lv_color_t),
|
||||
(const lv_color_t *)draw_ctx->buf, false) != LV_RES_OK)
|
||||
VG_LITE_RETURN_INV("Init buffer failed.");
|
||||
|
||||
/*** Init path ***/
|
||||
lv_coord_t width = dsc->width; /* inner arc radius = outer arc radius - width */
|
||||
if(width > (lv_coord_t)radius)
|
||||
width = radius;
|
||||
|
||||
int pidx = 0;
|
||||
int32_t cp_x, cp_y; /* control point coords */
|
||||
|
||||
/* first control point of curve */
|
||||
cp_x = radius;
|
||||
cp_y = 0;
|
||||
rotate_point(start_angle, &cp_x, &cp_y);
|
||||
arc_path[pidx++] = VLC_OP_MOVE;
|
||||
arc_path[pidx++] = clip_center.x + cp_x;
|
||||
arc_path[pidx++] = clip_center.y + cp_y;
|
||||
|
||||
/* draw 1-5 outer quarters */
|
||||
add_arc_path(arc_path, &pidx, radius, start_angle, end_angle, clip_center, true);
|
||||
|
||||
if(donut) {
|
||||
/* close outer circle */
|
||||
cp_x = radius;
|
||||
cp_y = 0;
|
||||
rotate_point(start_angle, &cp_x, &cp_y);
|
||||
arc_path[pidx++] = VLC_OP_LINE;
|
||||
arc_path[pidx++] = clip_center.x + cp_x;
|
||||
arc_path[pidx++] = clip_center.y + cp_y;
|
||||
/* start inner circle */
|
||||
cp_x = radius - width;
|
||||
cp_y = 0;
|
||||
rotate_point(start_angle, &cp_x, &cp_y);
|
||||
arc_path[pidx++] = VLC_OP_MOVE;
|
||||
arc_path[pidx++] = clip_center.x + cp_x;
|
||||
arc_path[pidx++] = clip_center.y + cp_y;
|
||||
|
||||
}
|
||||
else if(dsc->rounded != 0U) { /* 1st rounded arc ending */
|
||||
cp_x = radius - width / 2;
|
||||
cp_y = 0;
|
||||
rotate_point(end_angle, &cp_x, &cp_y);
|
||||
lv_point_t round_center = {clip_center.x + cp_x, clip_center.y + cp_y};
|
||||
add_arc_path(arc_path, &pidx, width / 2, end_angle, (end_angle + 180),
|
||||
round_center, true);
|
||||
|
||||
}
|
||||
else { /* 1st flat ending */
|
||||
cp_x = radius - width;
|
||||
cp_y = 0;
|
||||
rotate_point(end_angle, &cp_x, &cp_y);
|
||||
arc_path[pidx++] = VLC_OP_LINE;
|
||||
arc_path[pidx++] = clip_center.x + cp_x;
|
||||
arc_path[pidx++] = clip_center.y + cp_y;
|
||||
}
|
||||
|
||||
/* draw 1-5 inner quarters */
|
||||
add_arc_path(arc_path, &pidx, radius - width, start_angle, end_angle, clip_center, false);
|
||||
|
||||
/* last control point of curve */
|
||||
if(donut) { /* close the loop */
|
||||
cp_x = radius - width;
|
||||
cp_y = 0;
|
||||
rotate_point(start_angle, &cp_x, &cp_y);
|
||||
arc_path[pidx++] = VLC_OP_LINE;
|
||||
arc_path[pidx++] = clip_center.x + cp_x;
|
||||
arc_path[pidx++] = clip_center.y + cp_y;
|
||||
|
||||
}
|
||||
else if(dsc->rounded != 0U) { /* 2nd rounded arc ending */
|
||||
cp_x = radius - width / 2;
|
||||
cp_y = 0;
|
||||
rotate_point(start_angle, &cp_x, &cp_y);
|
||||
lv_point_t round_center = {clip_center.x + cp_x, clip_center.y + cp_y};
|
||||
add_arc_path(arc_path, &pidx, width / 2, (start_angle + 180), (start_angle + 360),
|
||||
round_center, true);
|
||||
|
||||
}
|
||||
else { /* 2nd flat ending */
|
||||
cp_x = radius;
|
||||
cp_y = 0;
|
||||
rotate_point(start_angle, &cp_x, &cp_y);
|
||||
arc_path[pidx++] = VLC_OP_LINE;
|
||||
arc_path[pidx++] = clip_center.x + cp_x;
|
||||
arc_path[pidx++] = clip_center.y + cp_y;
|
||||
}
|
||||
|
||||
arc_path[pidx++] = VLC_OP_END;
|
||||
|
||||
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, (uint32_t)pidx * sizeof(int32_t), arc_path,
|
||||
(vg_lite_float_t) draw_ctx->clip_area->x1, (vg_lite_float_t) draw_ctx->clip_area->y1,
|
||||
((vg_lite_float_t) draw_ctx->clip_area->x2) + 1.0f, ((vg_lite_float_t) draw_ctx->clip_area->y2) + 1.0f);
|
||||
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
|
||||
|
||||
/* set rotation angle */
|
||||
vg_lite_identity(&matrix);
|
||||
|
||||
if(opa <= (lv_opa_t)LV_OPA_MAX) {
|
||||
/* Only pre-multiply color if hardware pre-multiplication is not present */
|
||||
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
|
||||
col32.ch.red = (uint8_t)(((uint16_t)col32.ch.red * opa) >> 8);
|
||||
col32.ch.green = (uint8_t)(((uint16_t)col32.ch.green * opa) >> 8);
|
||||
col32.ch.blue = (uint8_t)(((uint16_t)col32.ch.blue * opa) >> 8);
|
||||
}
|
||||
col32.ch.alpha = opa;
|
||||
}
|
||||
|
||||
#if LV_COLOR_DEPTH==16
|
||||
vgcol = col32.full;
|
||||
#else /*LV_COLOR_DEPTH==32*/
|
||||
vgcol = ((uint32_t)col32.ch.alpha << 24) | ((uint32_t)col32.ch.blue << 16) | ((uint32_t)col32.ch.green << 8) |
|
||||
(uint32_t)col32.ch.red;
|
||||
#endif
|
||||
|
||||
/*Clean & invalidate cache*/
|
||||
lv_vglite_invalidate_cache();
|
||||
|
||||
/*** Draw arc ***/
|
||||
err = vg_lite_draw(&vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
|
||||
VG_LITE_ERR_RETURN_INV(err, "Draw arc failed.");
|
||||
|
||||
err = vg_lite_finish();
|
||||
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
|
||||
|
||||
err = vg_lite_clear_path(&path);
|
||||
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void copy_arc(vg_arc * dst, vg_arc * src)
|
||||
{
|
||||
dst->quarter = src->quarter;
|
||||
dst->rad = src->rad;
|
||||
dst->angle = src->angle;
|
||||
dst->p0x = src->p0x;
|
||||
dst->p1x = src->p1x;
|
||||
dst->p2x = src->p2x;
|
||||
dst->p3x = src->p3x;
|
||||
dst->p0y = src->p0y;
|
||||
dst->p1y = src->p1y;
|
||||
dst->p2y = src->p2y;
|
||||
dst->p3y = src->p3y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate the point according given rotation angle rotation center is 0,0
|
||||
*/
|
||||
static void rotate_point(int32_t angle, int32_t * x, int32_t * y)
|
||||
{
|
||||
int32_t ori_x = *x;
|
||||
int32_t ori_y = *y;
|
||||
int16_t alpha = (int16_t)angle;
|
||||
*x = ((lv_trigo_cos(alpha) * ori_x) / LV_TRIGO_SIN_MAX) - ((lv_trigo_sin(alpha) * ori_y) / LV_TRIGO_SIN_MAX);
|
||||
*y = ((lv_trigo_sin(alpha) * ori_x) / LV_TRIGO_SIN_MAX) + ((lv_trigo_cos(alpha) * ori_y) / LV_TRIGO_SIN_MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set full arc control points depending on quarter.
|
||||
* Control points match the best approximation of a circle.
|
||||
* Arc Quarter position is:
|
||||
* Q2 | Q3
|
||||
* ---+---
|
||||
* Q1 | Q0
|
||||
*/
|
||||
static void set_full_arc(vg_arc * fullarc)
|
||||
{
|
||||
/* the tangent lenght for the bezier circle approx */
|
||||
float tang = ((float)fullarc->rad) * BEZIER_OPTIM_CIRCLE;
|
||||
switch(fullarc->quarter) {
|
||||
case 0:
|
||||
/* first quarter */
|
||||
fullarc->p0x = fullarc->rad;
|
||||
fullarc->p0y = 0;
|
||||
fullarc->p1x = fullarc->rad;
|
||||
fullarc->p1y = (int32_t)tang;
|
||||
fullarc->p2x = (int32_t)tang;
|
||||
fullarc->p2y = fullarc->rad;
|
||||
fullarc->p3x = 0;
|
||||
fullarc->p3y = fullarc->rad;
|
||||
break;
|
||||
case 1:
|
||||
/* second quarter */
|
||||
fullarc->p0x = 0;
|
||||
fullarc->p0y = fullarc->rad;
|
||||
fullarc->p1x = 0 - (int32_t)tang;
|
||||
fullarc->p1y = fullarc->rad;
|
||||
fullarc->p2x = 0 - fullarc->rad;
|
||||
fullarc->p2y = (int32_t)tang;
|
||||
fullarc->p3x = 0 - fullarc->rad;
|
||||
fullarc->p3y = 0;
|
||||
break;
|
||||
case 2:
|
||||
/* third quarter */
|
||||
fullarc->p0x = 0 - fullarc->rad;
|
||||
fullarc->p0y = 0;
|
||||
fullarc->p1x = 0 - fullarc->rad;
|
||||
fullarc->p1y = 0 - (int32_t)tang;
|
||||
fullarc->p2x = 0 - (int32_t)tang;
|
||||
fullarc->p2y = 0 - fullarc->rad;
|
||||
fullarc->p3x = 0;
|
||||
fullarc->p3y = 0 - fullarc->rad;
|
||||
break;
|
||||
case 3:
|
||||
/* fourth quarter */
|
||||
fullarc->p0x = 0;
|
||||
fullarc->p0y = 0 - fullarc->rad;
|
||||
fullarc->p1x = (int32_t)tang;
|
||||
fullarc->p1y = 0 - fullarc->rad;
|
||||
fullarc->p2x = fullarc->rad;
|
||||
fullarc->p2y = 0 - (int32_t)tang;
|
||||
fullarc->p3x = fullarc->rad;
|
||||
fullarc->p3y = 0;
|
||||
break;
|
||||
default:
|
||||
LV_LOG_ERROR("Invalid arc quarter value.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Linear interpolation between two points 'a' and 'b'
|
||||
* 't' parameter is the proportion ratio expressed in range [0 ; T_FRACTION ]
|
||||
*/
|
||||
static inline float lerp(float coord_a, float coord_b, uint16_t t)
|
||||
{
|
||||
float tf = (float)t;
|
||||
return ((T_FRACTION - tf) * coord_a + tf * coord_b) / T_FRACTION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a point of bezier curve given 't' param
|
||||
*/
|
||||
static inline float comp_bezier_point(float t, cubic_cont_pt cp)
|
||||
{
|
||||
float t_sq = t * t;
|
||||
float inv_t_sq = (1.0f - t) * (1.0f - t);
|
||||
float apt = (1.0f - t) * inv_t_sq * cp.p0 + 3.0f * inv_t_sq * t * cp.p1 + 3.0f * (1.0f - t) * t_sq * cp.p2 + t * t_sq *
|
||||
cp.p3;
|
||||
return apt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find parameter 't' in curve at point 'pt'
|
||||
* proceed by dichotomy on only 1 dimension,
|
||||
* works only if the curve is monotonic
|
||||
* bezier curve is defined by control points [p0 p1 p2 p3]
|
||||
* 'dec' tells if curve is decreasing (true) or increasing (false)
|
||||
*/
|
||||
static uint16_t get_bez_t_from_pos(float pt, cubic_cont_pt cp, bool dec)
|
||||
{
|
||||
/* initialize dichotomy with boundary 't' values */
|
||||
float t_low = 0.0f;
|
||||
float t_mid = 0.5f;
|
||||
float t_hig = 1.0f;
|
||||
float a_pt;
|
||||
/* dichotomy loop */
|
||||
for(int i = 0; i < DICHOTO_ITER; i++) {
|
||||
a_pt = comp_bezier_point(t_mid, cp);
|
||||
/* check mid-point position on bezier curve versus targeted point */
|
||||
if((a_pt > pt) != dec) {
|
||||
t_hig = t_mid;
|
||||
}
|
||||
else {
|
||||
t_low = t_mid;
|
||||
}
|
||||
/* define new 't' param for mid-point */
|
||||
t_mid = (t_low + t_hig) / 2.0f;
|
||||
}
|
||||
/* return parameter 't' in integer range [0 ; T_FRACTION] */
|
||||
return (uint16_t)floorf(t_mid * T_FRACTION + 0.5f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives relative coords of the control points
|
||||
* for the sub-arc starting at angle with given angle span
|
||||
*/
|
||||
static void get_subarc_control_points(vg_arc * arc, int32_t span)
|
||||
{
|
||||
vg_arc fullarc;
|
||||
fullarc.angle = arc->angle;
|
||||
fullarc.quarter = arc->quarter;
|
||||
fullarc.rad = arc->rad;
|
||||
set_full_arc(&fullarc);
|
||||
|
||||
/* special case of full arc */
|
||||
if(arc->angle == 90) {
|
||||
copy_arc(arc, &fullarc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* compute 1st arc using the geometric construction of curve */
|
||||
uint16_t t2 = TperDegree[arc->angle + span];
|
||||
|
||||
/* lerp for A */
|
||||
float a2x = lerp((float)fullarc.p0x, (float)fullarc.p1x, t2);
|
||||
float a2y = lerp((float)fullarc.p0y, (float)fullarc.p1y, t2);
|
||||
/* lerp for B */
|
||||
float b2x = lerp((float)fullarc.p1x, (float)fullarc.p2x, t2);
|
||||
float b2y = lerp((float)fullarc.p1y, (float)fullarc.p2y, t2);
|
||||
/* lerp for C */
|
||||
float c2x = lerp((float)fullarc.p2x, (float)fullarc.p3x, t2);
|
||||
float c2y = lerp((float)fullarc.p2y, (float)fullarc.p3y, t2);
|
||||
|
||||
/* lerp for D */
|
||||
float d2x = lerp(a2x, b2x, t2);
|
||||
float d2y = lerp(a2y, b2y, t2);
|
||||
/* lerp for E */
|
||||
float e2x = lerp(b2x, c2x, t2);
|
||||
float e2y = lerp(b2y, c2y, t2);
|
||||
|
||||
float pt2x = lerp(d2x, e2x, t2);
|
||||
float pt2y = lerp(d2y, e2y, t2);
|
||||
|
||||
/* compute sub-arc using the geometric construction of curve */
|
||||
uint16_t t1 = TperDegree[arc->angle];
|
||||
|
||||
/* lerp for A */
|
||||
float a1x = lerp((float)fullarc.p0x, (float)fullarc.p1x, t1);
|
||||
float a1y = lerp((float)fullarc.p0y, (float)fullarc.p1y, t1);
|
||||
/* lerp for B */
|
||||
float b1x = lerp((float)fullarc.p1x, (float)fullarc.p2x, t1);
|
||||
float b1y = lerp((float)fullarc.p1y, (float)fullarc.p2y, t1);
|
||||
/* lerp for C */
|
||||
float c1x = lerp((float)fullarc.p2x, (float)fullarc.p3x, t1);
|
||||
float c1y = lerp((float)fullarc.p2y, (float)fullarc.p3y, t1);
|
||||
|
||||
/* lerp for D */
|
||||
float d1x = lerp(a1x, b1x, t1);
|
||||
float d1y = lerp(a1y, b1y, t1);
|
||||
/* lerp for E */
|
||||
float e1x = lerp(b1x, c1x, t1);
|
||||
float e1y = lerp(b1y, c1y, t1);
|
||||
|
||||
float pt1x = lerp(d1x, e1x, t1);
|
||||
float pt1y = lerp(d1y, e1y, t1);
|
||||
|
||||
/* find the 't3' parameter for point P(t1) on the sub-arc [P0 A2 D2 P(t2)] using dichotomy
|
||||
* use position of x axis only */
|
||||
uint16_t t3;
|
||||
t3 = get_bez_t_from_pos(pt1x,
|
||||
(cubic_cont_pt) {
|
||||
.p0 = ((float)fullarc.p0x), .p1 = a2x, .p2 = d2x, .p3 = pt2x
|
||||
},
|
||||
(bool)(pt2x < (float)fullarc.p0x));
|
||||
|
||||
/* lerp for B */
|
||||
float b3x = lerp(a2x, d2x, t3);
|
||||
float b3y = lerp(a2y, d2y, t3);
|
||||
/* lerp for C */
|
||||
float c3x = lerp(d2x, pt2x, t3);
|
||||
float c3y = lerp(d2y, pt2y, t3);
|
||||
|
||||
/* lerp for E */
|
||||
float e3x = lerp(b3x, c3x, t3);
|
||||
float e3y = lerp(b3y, c3y, t3);
|
||||
|
||||
arc->p0x = (int32_t)floorf(0.5f + pt1x);
|
||||
arc->p0y = (int32_t)floorf(0.5f + pt1y);
|
||||
arc->p1x = (int32_t)floorf(0.5f + e3x);
|
||||
arc->p1y = (int32_t)floorf(0.5f + e3y);
|
||||
arc->p2x = (int32_t)floorf(0.5f + c3x);
|
||||
arc->p2y = (int32_t)floorf(0.5f + c3y);
|
||||
arc->p3x = (int32_t)floorf(0.5f + pt2x);
|
||||
arc->p3y = (int32_t)floorf(0.5f + pt2y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives relative coords of the control points
|
||||
*/
|
||||
static void get_arc_control_points(vg_arc * arc, bool start)
|
||||
{
|
||||
vg_arc fullarc;
|
||||
fullarc.angle = arc->angle;
|
||||
fullarc.quarter = arc->quarter;
|
||||
fullarc.rad = arc->rad;
|
||||
set_full_arc(&fullarc);
|
||||
|
||||
/* special case of full arc */
|
||||
if(arc->angle == 90) {
|
||||
copy_arc(arc, &fullarc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* compute sub-arc using the geometric construction of curve */
|
||||
uint16_t t = TperDegree[arc->angle];
|
||||
/* lerp for A */
|
||||
float ax = lerp((float)fullarc.p0x, (float)fullarc.p1x, t);
|
||||
float ay = lerp((float)fullarc.p0y, (float)fullarc.p1y, t);
|
||||
/* lerp for B */
|
||||
float bx = lerp((float)fullarc.p1x, (float)fullarc.p2x, t);
|
||||
float by = lerp((float)fullarc.p1y, (float)fullarc.p2y, t);
|
||||
/* lerp for C */
|
||||
float cx = lerp((float)fullarc.p2x, (float)fullarc.p3x, t);
|
||||
float cy = lerp((float)fullarc.p2y, (float)fullarc.p3y, t);
|
||||
|
||||
/* lerp for D */
|
||||
float dx = lerp(ax, bx, t);
|
||||
float dy = lerp(ay, by, t);
|
||||
/* lerp for E */
|
||||
float ex = lerp(bx, cx, t);
|
||||
float ey = lerp(by, cy, t);
|
||||
|
||||
/* sub-arc's control points are tangents of DeCasteljau's algorithm */
|
||||
if(start) {
|
||||
arc->p0x = (int32_t)floorf(0.5f + lerp(dx, ex, t));
|
||||
arc->p0y = (int32_t)floorf(0.5f + lerp(dy, ey, t));
|
||||
arc->p1x = (int32_t)floorf(0.5f + ex);
|
||||
arc->p1y = (int32_t)floorf(0.5f + ey);
|
||||
arc->p2x = (int32_t)floorf(0.5f + cx);
|
||||
arc->p2y = (int32_t)floorf(0.5f + cy);
|
||||
arc->p3x = fullarc.p3x;
|
||||
arc->p3y = fullarc.p3y;
|
||||
}
|
||||
else {
|
||||
arc->p0x = fullarc.p0x;
|
||||
arc->p0y = fullarc.p0y;
|
||||
arc->p1x = (int32_t)floorf(0.5f + ax);
|
||||
arc->p1y = (int32_t)floorf(0.5f + ay);
|
||||
arc->p2x = (int32_t)floorf(0.5f + dx);
|
||||
arc->p2y = (int32_t)floorf(0.5f + dy);
|
||||
arc->p3x = (int32_t)floorf(0.5f + lerp(dx, ex, t));
|
||||
arc->p3y = (int32_t)floorf(0.5f + lerp(dy, ey, t));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the arc control points into the path data for vglite,
|
||||
* taking into account the real center of the arc (translation).
|
||||
* arc_path: (in/out) the path data array for vglite
|
||||
* pidx: (in/out) index of last element added in arc_path
|
||||
* q_arc: (in) the arc data containing control points
|
||||
* center: (in) the center of the circle in draw coordinates
|
||||
* cw: (in) true if arc is clockwise
|
||||
*/
|
||||
static void add_split_arc_path(int32_t * arc_path, int * pidx, vg_arc * q_arc, lv_point_t center, bool cw)
|
||||
{
|
||||
/* assumes first control point already in array arc_path[] */
|
||||
int idx = *pidx;
|
||||
if(cw) {
|
||||
#if BEZIER_DBG_CONTROL_POINTS
|
||||
arc_path[idx++] = VLC_OP_LINE;
|
||||
arc_path[idx++] = q_arc->p1x + center.x;
|
||||
arc_path[idx++] = q_arc->p1y + center.y;
|
||||
arc_path[idx++] = VLC_OP_LINE;
|
||||
arc_path[idx++] = q_arc->p2x + center.x;
|
||||
arc_path[idx++] = q_arc->p2y + center.y;
|
||||
arc_path[idx++] = VLC_OP_LINE;
|
||||
arc_path[idx++] = q_arc->p3x + center.x;
|
||||
arc_path[idx++] = q_arc->p3y + center.y;
|
||||
#else
|
||||
arc_path[idx++] = VLC_OP_CUBIC;
|
||||
arc_path[idx++] = q_arc->p1x + center.x;
|
||||
arc_path[idx++] = q_arc->p1y + center.y;
|
||||
arc_path[idx++] = q_arc->p2x + center.x;
|
||||
arc_path[idx++] = q_arc->p2y + center.y;
|
||||
arc_path[idx++] = q_arc->p3x + center.x;
|
||||
arc_path[idx++] = q_arc->p3y + center.y;
|
||||
#endif
|
||||
}
|
||||
else { /* reverse points order when counter-clockwise */
|
||||
#if BEZIER_DBG_CONTROL_POINTS
|
||||
arc_path[idx++] = VLC_OP_LINE;
|
||||
arc_path[idx++] = q_arc->p2x + center.x;
|
||||
arc_path[idx++] = q_arc->p2y + center.y;
|
||||
arc_path[idx++] = VLC_OP_LINE;
|
||||
arc_path[idx++] = q_arc->p1x + center.x;
|
||||
arc_path[idx++] = q_arc->p1y + center.y;
|
||||
arc_path[idx++] = VLC_OP_LINE;
|
||||
arc_path[idx++] = q_arc->p0x + center.x;
|
||||
arc_path[idx++] = q_arc->p0y + center.y;
|
||||
#else
|
||||
arc_path[idx++] = VLC_OP_CUBIC;
|
||||
arc_path[idx++] = q_arc->p2x + center.x;
|
||||
arc_path[idx++] = q_arc->p2y + center.y;
|
||||
arc_path[idx++] = q_arc->p1x + center.x;
|
||||
arc_path[idx++] = q_arc->p1y + center.y;
|
||||
arc_path[idx++] = q_arc->p0x + center.x;
|
||||
arc_path[idx++] = q_arc->p0y + center.y;
|
||||
#endif
|
||||
}
|
||||
/* update index i n path array*/
|
||||
*pidx = idx;
|
||||
}
|
||||
|
||||
static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius,
|
||||
int32_t start_angle, int32_t end_angle, lv_point_t center, bool cw)
|
||||
{
|
||||
/* set number of arcs to draw */
|
||||
vg_arc q_arc;
|
||||
int32_t start_arc_angle = start_angle % 90;
|
||||
int32_t end_arc_angle = end_angle % 90;
|
||||
int32_t inv_start_arc_angle = (start_arc_angle > 0) ? (90 - start_arc_angle) : 0;
|
||||
int32_t nbarc = (end_angle - start_angle - inv_start_arc_angle - end_arc_angle) / 90;
|
||||
q_arc.rad = radius;
|
||||
|
||||
/* handle special case of start & end point in the same quarter */
|
||||
if(((start_angle / 90) == (end_angle / 90)) && (nbarc <= 0)) {
|
||||
q_arc.quarter = (start_angle / 90) % 4;
|
||||
q_arc.angle = start_arc_angle;
|
||||
get_subarc_control_points(&q_arc, end_arc_angle - start_arc_angle);
|
||||
add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
|
||||
return;
|
||||
}
|
||||
|
||||
if(cw) {
|
||||
/* partial starting arc */
|
||||
if(start_arc_angle > 0) {
|
||||
q_arc.quarter = (start_angle / 90) % 4;
|
||||
q_arc.angle = start_arc_angle;
|
||||
/* get cubic points relative to center */
|
||||
get_arc_control_points(&q_arc, true);
|
||||
/* put cubic points in arc_path */
|
||||
add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
|
||||
}
|
||||
/* full arcs */
|
||||
for(int32_t q = 0; q < nbarc ; q++) {
|
||||
q_arc.quarter = (q + ((start_angle + 89) / 90)) % 4;
|
||||
q_arc.angle = 90;
|
||||
/* get cubic points relative to center */
|
||||
get_arc_control_points(&q_arc, true); /* 2nd parameter 'start' ignored */
|
||||
/* put cubic points in arc_path */
|
||||
add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
|
||||
}
|
||||
/* partial ending arc */
|
||||
if(end_arc_angle > 0) {
|
||||
q_arc.quarter = (end_angle / 90) % 4;
|
||||
q_arc.angle = end_arc_angle;
|
||||
/* get cubic points relative to center */
|
||||
get_arc_control_points(&q_arc, false);
|
||||
/* put cubic points in arc_path */
|
||||
add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
|
||||
}
|
||||
|
||||
}
|
||||
else { /* counter clockwise */
|
||||
|
||||
/* partial ending arc */
|
||||
if(end_arc_angle > 0) {
|
||||
q_arc.quarter = (end_angle / 90) % 4;
|
||||
q_arc.angle = end_arc_angle;
|
||||
/* get cubic points relative to center */
|
||||
get_arc_control_points(&q_arc, false);
|
||||
/* put cubic points in arc_path */
|
||||
add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
|
||||
}
|
||||
/* full arcs */
|
||||
for(int32_t q = nbarc - 1; q >= 0; q--) {
|
||||
q_arc.quarter = (q + ((start_angle + 89) / 90)) % 4;
|
||||
q_arc.angle = 90;
|
||||
/* get cubic points relative to center */
|
||||
get_arc_control_points(&q_arc, true); /* 2nd parameter 'start' ignored */
|
||||
/* put cubic points in arc_path */
|
||||
add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
|
||||
}
|
||||
/* partial starting arc */
|
||||
if(start_arc_angle > 0) {
|
||||
q_arc.quarter = (start_angle / 90) % 4;
|
||||
q_arc.angle = start_arc_angle;
|
||||
/* get cubic points relative to center */
|
||||
get_arc_control_points(&q_arc, true);
|
||||
/* put cubic points in arc_path */
|
||||
add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_arc.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2021, 2022 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_DRAW_VGLITE_ARC_H
|
||||
#define LV_DRAW_VGLITE_ARC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
#include "lv_gpu_nxp_vglite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/***
|
||||
* Draw arc shape with effects
|
||||
* @param draw_ctx drawing context
|
||||
* @param dsc the arc description structure (width, rounded ending, opacity)
|
||||
* @param center the coordinates of the arc center
|
||||
* @param radius the radius of external arc
|
||||
* @param start_angle the starting angle in degrees
|
||||
* @param end_angle the ending angle in degrees
|
||||
*/
|
||||
lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
||||
int32_t radius, int32_t start_angle, int32_t end_angle);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_VGLITE_ARC_H*/
|
||||
@@ -0,0 +1,618 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_blend.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2020-2022 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_vglite_blend.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/* Enable BLIT quality degradation workaround for RT595, recommended for screen's dimension > 352 pixels */
|
||||
#define RT595_BLIT_WRKRND_ENABLED 1
|
||||
|
||||
/* Internal compound symbol */
|
||||
#if (defined(CPU_MIMXRT595SFFOB) || defined(CPU_MIMXRT595SFFOB_cm33) || \
|
||||
defined(CPU_MIMXRT595SFFOC) || defined(CPU_MIMXRT595SFFOC_cm33)) && \
|
||||
RT595_BLIT_WRKRND_ENABLED
|
||||
#define VG_LITE_BLIT_SPLIT_ENABLED 1
|
||||
#else
|
||||
#define VG_LITE_BLIT_SPLIT_ENABLED 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* BLIT split threshold - BLITs with width or height higher than this value will be done
|
||||
* in multiple steps. Value must be 16-aligned. Don't change.
|
||||
*/
|
||||
#define LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR 352
|
||||
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* BLock Image Transfer - single direct BLIT.
|
||||
*
|
||||
* @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)
|
||||
*/
|
||||
static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit);
|
||||
|
||||
#if VG_LITE_BLIT_SPLIT_ENABLED
|
||||
|
||||
/**
|
||||
* Move buffer pointer as close as possible to area, but with respect to alignment requirements. X-axis only.
|
||||
*
|
||||
* @param[in,out] area Area to be updated
|
||||
* @param[in,out] buf Pointer to be updated
|
||||
*/
|
||||
static void _align_x(lv_area_t * area, lv_color_t ** buf);
|
||||
|
||||
/**
|
||||
* Move buffer pointer to the area start and update variables, Y-axis only.
|
||||
*
|
||||
* @param[in,out] area Area to be updated
|
||||
* @param[in,out] buf Pointer to be updated
|
||||
* @param[in] stridePx Buffer stride in pixels
|
||||
*/
|
||||
static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx);
|
||||
|
||||
/**
|
||||
* Software BLIT as a fall-back scenario.
|
||||
*
|
||||
* @param[in] blit BLIT configuration
|
||||
*/
|
||||
static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit);
|
||||
|
||||
/**
|
||||
* Verify BLIT structure - widths, stride, pointer alignment
|
||||
*
|
||||
* @param[in] blit BLIT configuration
|
||||
* @retval LV_RES_OK
|
||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||
*/
|
||||
static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit);
|
||||
|
||||
/**
|
||||
* BLock Image Transfer - split BLIT.
|
||||
*
|
||||
* @param[in] blit BLIT configuration
|
||||
* @retval LV_RES_OK Transfer complete
|
||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||
*/
|
||||
static lv_res_t _lv_gpu_nxp_vglite_blit_split(lv_gpu_nxp_vglite_blit_info_t * blit);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
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)
|
||||
{
|
||||
uint32_t area_size = lv_area_get_size(fill_area);
|
||||
lv_coord_t area_w = lv_area_get_width(fill_area);
|
||||
lv_coord_t area_h = lv_area_get_height(fill_area);
|
||||
|
||||
if(opa >= (lv_opa_t)LV_OPA_MAX) {
|
||||
if(area_size < LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT)
|
||||
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT);
|
||||
}
|
||||
else {
|
||||
if(area_size < LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT)
|
||||
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT);
|
||||
}
|
||||
|
||||
vg_lite_buffer_t vgbuf;
|
||||
vg_lite_rectangle_t rect;
|
||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||
lv_color32_t col32 = {.full = lv_color_to32(color)}; /*Convert color to RGBA8888*/
|
||||
vg_lite_color_t vgcol; /* vglite takes ABGR */
|
||||
|
||||
if(lv_vglite_init_buf(&vgbuf, (uint32_t)dest_width, (uint32_t)dest_height, (uint32_t)dest_width * sizeof(lv_color_t),
|
||||
(const lv_color_t *)dest_buf, false) != LV_RES_OK)
|
||||
VG_LITE_RETURN_INV("Init buffer failed.");
|
||||
|
||||
if(opa >= (lv_opa_t)LV_OPA_MAX) { /*Opaque fill*/
|
||||
rect.x = fill_area->x1;
|
||||
rect.y = fill_area->y1;
|
||||
rect.width = area_w;
|
||||
rect.height = area_h;
|
||||
|
||||
/*Clean & invalidate cache*/
|
||||
lv_vglite_invalidate_cache();
|
||||
|
||||
#if LV_COLOR_DEPTH==16
|
||||
vgcol = col32.full;
|
||||
#else /*LV_COLOR_DEPTH==32*/
|
||||
vgcol = ((uint32_t)col32.ch.alpha << 24) | ((uint32_t)col32.ch.blue << 16) | ((uint32_t)col32.ch.green << 8) |
|
||||
(uint32_t)col32.ch.red;
|
||||
#endif
|
||||
|
||||
err = vg_lite_clear(&vgbuf, &rect, vgcol);
|
||||
VG_LITE_ERR_RETURN_INV(err, "Clear failed.");
|
||||
|
||||
err = vg_lite_finish();
|
||||
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
|
||||
}
|
||||
else { /*fill with transparency*/
|
||||
|
||||
vg_lite_path_t path;
|
||||
int32_t path_data[] = { /*VG rectangular path*/
|
||||
VLC_OP_MOVE, fill_area->x1, fill_area->y1,
|
||||
VLC_OP_LINE, fill_area->x2 + 1, fill_area->y1,
|
||||
VLC_OP_LINE, fill_area->x2 + 1, fill_area->y2 + 1,
|
||||
VLC_OP_LINE, fill_area->x1, fill_area->y2 + 1,
|
||||
VLC_OP_LINE, fill_area->x1, fill_area->y1,
|
||||
VLC_OP_END
|
||||
};
|
||||
|
||||
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_LOW, sizeof(path_data), path_data,
|
||||
(vg_lite_float_t) fill_area->x1, (vg_lite_float_t) fill_area->y1,
|
||||
((vg_lite_float_t) fill_area->x2) + 1.0f, ((vg_lite_float_t) fill_area->y2) + 1.0f);
|
||||
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
|
||||
|
||||
/* Only pre-multiply color if hardware pre-multiplication is not present */
|
||||
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
|
||||
col32.ch.red = (uint8_t)(((uint16_t)col32.ch.red * opa) >> 8);
|
||||
col32.ch.green = (uint8_t)(((uint16_t)col32.ch.green * opa) >> 8);
|
||||
col32.ch.blue = (uint8_t)(((uint16_t)col32.ch.blue * opa) >> 8);
|
||||
}
|
||||
col32.ch.alpha = opa;
|
||||
|
||||
#if LV_COLOR_DEPTH==16
|
||||
vgcol = col32.full;
|
||||
#else /*LV_COLOR_DEPTH==32*/
|
||||
vgcol = ((uint32_t)col32.ch.alpha << 24) | ((uint32_t)col32.ch.blue << 16) | ((uint32_t)col32.ch.green << 8) |
|
||||
(uint32_t)col32.ch.red;
|
||||
#endif
|
||||
|
||||
/*Clean & invalidate cache*/
|
||||
lv_vglite_invalidate_cache();
|
||||
|
||||
vg_lite_matrix_t matrix;
|
||||
vg_lite_identity(&matrix);
|
||||
|
||||
/*Draw rectangle*/
|
||||
err = vg_lite_draw(&vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
|
||||
VG_LITE_ERR_RETURN_INV(err, "Draw rectangle failed.");
|
||||
|
||||
err = vg_lite_finish();
|
||||
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
|
||||
|
||||
err = vg_lite_clear_path(&path);
|
||||
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit)
|
||||
{
|
||||
uint32_t dest_size = lv_area_get_size(&blit->dst_area);
|
||||
|
||||
if(blit->opa >= (lv_opa_t)LV_OPA_MAX) {
|
||||
if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT)
|
||||
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT);
|
||||
}
|
||||
else {
|
||||
if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT)
|
||||
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT);
|
||||
}
|
||||
|
||||
#if VG_LITE_BLIT_SPLIT_ENABLED
|
||||
return _lv_gpu_nxp_vglite_blit_split(blit);
|
||||
#endif /* non RT595 */
|
||||
|
||||
/* Just pass down */
|
||||
return _lv_gpu_nxp_vglite_blit_single(blit);
|
||||
}
|
||||
|
||||
lv_res_t lv_gpu_nxp_vglite_blit_transform(lv_gpu_nxp_vglite_blit_info_t * blit)
|
||||
{
|
||||
uint32_t dest_size = lv_area_get_size(&blit->dst_area);
|
||||
|
||||
if(blit->opa >= (lv_opa_t)LV_OPA_MAX) {
|
||||
if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT)
|
||||
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT);
|
||||
}
|
||||
else {
|
||||
if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT)
|
||||
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT);
|
||||
}
|
||||
|
||||
return _lv_gpu_nxp_vglite_blit_single(blit);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if VG_LITE_BLIT_SPLIT_ENABLED
|
||||
static lv_res_t _lv_gpu_nxp_vglite_blit_split(lv_gpu_nxp_vglite_blit_info_t * blit)
|
||||
{
|
||||
lv_res_t rv = LV_RES_INV;
|
||||
|
||||
if(_lv_gpu_nxp_vglite_check_blit(blit) != LV_RES_OK) {
|
||||
PRINT_BLT("Blit check failed\n");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
PRINT_BLT("BLIT from: "
|
||||
"Area: %03d,%03d - %03d,%03d "
|
||||
"Addr: %d\n\n",
|
||||
blit->src_area.x1, blit->src_area.y1,
|
||||
blit->src_area.x2, blit->src_area.y2,
|
||||
(uintptr_t) blit->src);
|
||||
|
||||
PRINT_BLT("BLIT to: "
|
||||
"Area: %03d,%03d - %03d,%03d "
|
||||
"Addr: %d\n\n",
|
||||
blit->dst_area.x1, blit->dst_area.y1,
|
||||
blit->dst_area.x2, blit->dst_area.y2,
|
||||
(uintptr_t) blit->src);
|
||||
|
||||
/* Stage 1: Move starting pointers as close as possible to [x1, y1], so coordinates are as small as possible. */
|
||||
_align_x(&blit->src_area, (lv_color_t **)&blit->src);
|
||||
_align_y(&blit->src_area, (lv_color_t **)&blit->src, blit->src_stride / sizeof(lv_color_t));
|
||||
_align_x(&blit->dst_area, (lv_color_t **)&blit->dst);
|
||||
_align_y(&blit->dst_area, (lv_color_t **)&blit->dst, blit->dst_stride / sizeof(lv_color_t));
|
||||
|
||||
/* Stage 2: If we're in limit, do a single BLIT */
|
||||
if((blit->src_area.x2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) &&
|
||||
(blit->src_area.y2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR)) {
|
||||
PRINT_BLT("Simple blit!\n");
|
||||
return _lv_gpu_nxp_vglite_blit_single(blit);
|
||||
};
|
||||
|
||||
/* Stage 3: Split the BLIT into multiple tiles */
|
||||
PRINT_BLT("Split blit!\n");
|
||||
|
||||
PRINT_BLT("Blit "
|
||||
"([%03d,%03d], [%03d,%03d]) -> "
|
||||
"([%03d,%03d], [%03d,%03d]) | "
|
||||
"([%03dx%03d] -> [%03dx%03d]) | "
|
||||
"A:(%d -> %d)\n",
|
||||
blit->src_area.x1, blit->src_area.y1, blit->src_area.x2, blit->src_area.y2,
|
||||
blit->dst_area.x1, blit->dst_area.y1, blit->dst_area.x2, blit->dst_area.y2,
|
||||
lv_area_get_width(&blit->src_area), lv_area_get_height(&blit->src_area),
|
||||
lv_area_get_width(&blit->dst_area), lv_area_get_height(&blit->dst_area),
|
||||
(uintptr_t) blit->src, (uintptr_t) blit->dst);
|
||||
|
||||
|
||||
lv_coord_t totalWidth = lv_area_get_width(&blit->src_area);
|
||||
lv_coord_t totalHeight = lv_area_get_height(&blit->src_area);
|
||||
|
||||
lv_gpu_nxp_vglite_blit_info_t tileBlit;
|
||||
|
||||
/* Number of tiles needed */
|
||||
int totalTilesX = (blit->src_area.x1 + totalWidth + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) /
|
||||
LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
||||
int totalTilesY = (blit->src_area.y1 + totalHeight + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) /
|
||||
LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
||||
|
||||
/* src and dst buffer shift against each other. Src buffer real data [0,0] may start actually at [3,0] in buffer, as
|
||||
* the buffer pointer has to be aligned, while dst buffer real data [0,0] may start at [1,0] in buffer. alignment may be
|
||||
* different */
|
||||
int shiftSrcX = (blit->src_area.x1 > blit->dst_area.x1) ? (blit->src_area.x1 - blit->dst_area.x1) : 0;
|
||||
int shiftDstX = (blit->src_area.x1 < blit->dst_area.x1) ? (blit->dst_area.x1 - blit->src_area.x1) : 0;
|
||||
|
||||
PRINT_BLT("\n");
|
||||
PRINT_BLT("Align shift: src: %d, dst: %d\n", shiftSrcX, shiftDstX);
|
||||
|
||||
tileBlit = *blit;
|
||||
|
||||
for(int tileY = 0; tileY < totalTilesY; tileY++) {
|
||||
|
||||
tileBlit.src_area.y1 = 0; /* no vertical alignment, always start from 0 */
|
||||
tileBlit.src_area.y2 = totalHeight - tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||
if(tileBlit.src_area.y2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
|
||||
tileBlit.src_area.y2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; /* Should never happen */
|
||||
}
|
||||
tileBlit.src = blit->src + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->src_stride / sizeof(
|
||||
lv_color_t); /* stride in px! */
|
||||
|
||||
tileBlit.dst_area.y1 = tileBlit.src_area.y1; /* y has no alignment, always in sync with src */
|
||||
tileBlit.dst_area.y2 = tileBlit.src_area.y2;
|
||||
|
||||
tileBlit.dst = blit->dst + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->dst_stride / sizeof(
|
||||
lv_color_t); /* stride in px! */
|
||||
|
||||
for(int tileX = 0; tileX < totalTilesX; tileX++) {
|
||||
|
||||
if(tileX == 0) {
|
||||
/* 1st tile is special - there may be a gap between buffer start pointer
|
||||
* and area.x1 value, as the pointer has to be aligned.
|
||||
* tileBlit.src pointer - keep init value from Y-loop.
|
||||
* Also, 1st tile start is not shifted! shift is applied from 2nd tile */
|
||||
tileBlit.src_area.x1 = blit->src_area.x1;
|
||||
tileBlit.dst_area.x1 = blit->dst_area.x1;
|
||||
}
|
||||
else {
|
||||
/* subsequent tiles always starts from 0, but shifted*/
|
||||
tileBlit.src_area.x1 = 0 + shiftSrcX;
|
||||
tileBlit.dst_area.x1 = 0 + shiftDstX;
|
||||
/* and advance start pointer + 1 tile size */
|
||||
tileBlit.src += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
||||
tileBlit.dst += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
||||
}
|
||||
|
||||
/* Clip tile end coordinates */
|
||||
tileBlit.src_area.x2 = totalWidth + blit->src_area.x1 - tileX * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||
if(tileBlit.src_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
|
||||
tileBlit.src_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||
}
|
||||
|
||||
tileBlit.dst_area.x2 = totalWidth + blit->dst_area.x1 - tileX * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||
if(tileBlit.dst_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
|
||||
tileBlit.dst_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||
}
|
||||
|
||||
if(tileX < (totalTilesX - 1)) {
|
||||
/* And adjust end coords if shifted, but not for last tile! */
|
||||
tileBlit.src_area.x2 += shiftSrcX;
|
||||
tileBlit.dst_area.x2 += shiftDstX;
|
||||
}
|
||||
|
||||
rv = _lv_gpu_nxp_vglite_blit_single(&tileBlit);
|
||||
|
||||
#if BLIT_DBG_AREAS
|
||||
lv_vglite_dbg_draw_rectangle((lv_color_t *) tileBlit.dst, tileBlit.dst_width, tileBlit.dst_height, &tileBlit.dst_area,
|
||||
LV_COLOR_RED);
|
||||
lv_vglite_dbg_draw_rectangle((lv_color_t *) tileBlit.src, tileBlit.src_width, tileBlit.src_height, &tileBlit.src_area,
|
||||
LV_COLOR_GREEN);
|
||||
#endif
|
||||
|
||||
PRINT_BLT("Tile [%d, %d]: "
|
||||
"([%d,%d], [%d,%d]) -> "
|
||||
"([%d,%d], [%d,%d]) | "
|
||||
"([%dx%d] -> [%dx%d]) | "
|
||||
"A:(0x%8X -> 0x%8X) %s\n",
|
||||
tileX, tileY,
|
||||
tileBlit.src_area.x1, tileBlit.src_area.y1, tileBlit.src_area.x2, tileBlit.src_area.y2,
|
||||
tileBlit.dst_area.x1, tileBlit.dst_area.y1, tileBlit.dst_area.x2, tileBlit.dst_area.y2,
|
||||
lv_area_get_width(&tileBlit.src_area), lv_area_get_height(&tileBlit.src_area),
|
||||
lv_area_get_width(&tileBlit.dst_area), lv_area_get_height(&tileBlit.dst_area),
|
||||
(uintptr_t) tileBlit.src, (uintptr_t) tileBlit.dst,
|
||||
rv == LV_RES_OK ? "OK!" : "!!! FAILED !!!");
|
||||
|
||||
if(rv != LV_RES_OK) { /* if anything goes wrong... */
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("Split blit failed. Trying SW blit instead.");
|
||||
#endif
|
||||
_sw_blit(&tileBlit);
|
||||
rv = LV_RES_OK; /* Don't report error, as SW BLIT was performed */
|
||||
}
|
||||
|
||||
}
|
||||
PRINT_BLT(" \n");
|
||||
}
|
||||
|
||||
return rv; /* should never fail */
|
||||
}
|
||||
#endif /* VG_LITE_BLIT_SPLIT_ENABLED */
|
||||
|
||||
static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit)
|
||||
{
|
||||
vg_lite_buffer_t src_vgbuf, dst_vgbuf;
|
||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||
uint32_t rect[4];
|
||||
vg_lite_float_t scale = 1.0;
|
||||
|
||||
if(blit == NULL) {
|
||||
/*Wrong parameter*/
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
if(blit->opa < (lv_opa_t) LV_OPA_MIN) {
|
||||
return LV_RES_OK; /*Nothing to BLIT*/
|
||||
}
|
||||
|
||||
/*Wrap src/dst buffer into VG-Lite buffer*/
|
||||
if(lv_vglite_init_buf(&src_vgbuf, (uint32_t)blit->src_width, (uint32_t)blit->src_height, (uint32_t)blit->src_stride,
|
||||
blit->src, true) != LV_RES_OK)
|
||||
VG_LITE_RETURN_INV("Init buffer failed.");
|
||||
|
||||
if(lv_vglite_init_buf(&dst_vgbuf, (uint32_t)blit->dst_width, (uint32_t)blit->dst_height, (uint32_t)blit->dst_stride,
|
||||
blit->dst, false) != LV_RES_OK)
|
||||
VG_LITE_RETURN_INV("Init buffer failed.");
|
||||
|
||||
rect[0] = (uint32_t)blit->src_area.x1; /* start x */
|
||||
rect[1] = (uint32_t)blit->src_area.y1; /* start y */
|
||||
rect[2] = (uint32_t)blit->src_area.x2 - (uint32_t)blit->src_area.x1 + 1U; /* width */
|
||||
rect[3] = (uint32_t)blit->src_area.y2 - (uint32_t)blit->src_area.y1 + 1U; /* height */
|
||||
|
||||
vg_lite_matrix_t matrix;
|
||||
vg_lite_identity(&matrix);
|
||||
vg_lite_translate((vg_lite_float_t)blit->dst_area.x1, (vg_lite_float_t)blit->dst_area.y1, &matrix);
|
||||
|
||||
if((blit->angle != 0) || (blit->zoom != LV_IMG_ZOOM_NONE)) {
|
||||
vg_lite_translate(blit->pivot.x, blit->pivot.y, &matrix);
|
||||
vg_lite_rotate(blit->angle / 10.0f, &matrix); /* angle is 1/10 degree */
|
||||
scale = 1.0f * blit->zoom / LV_IMG_ZOOM_NONE;
|
||||
vg_lite_scale(scale, scale, &matrix);
|
||||
vg_lite_translate(0.0f - blit->pivot.x, 0.0f - blit->pivot.y, &matrix);
|
||||
}
|
||||
|
||||
/*Clean & invalidate cache*/
|
||||
lv_vglite_invalidate_cache();
|
||||
|
||||
uint32_t color;
|
||||
vg_lite_blend_t blend;
|
||||
if(blit->opa >= (lv_opa_t)LV_OPA_MAX) {
|
||||
color = 0xFFFFFFFFU;
|
||||
blend = VG_LITE_BLEND_SRC_OVER;
|
||||
src_vgbuf.transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
|
||||
}
|
||||
else {
|
||||
uint32_t opa = (uint32_t)blit->opa;
|
||||
if(vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
|
||||
color = (opa << 24) | 0x00FFFFFFU;
|
||||
}
|
||||
else {
|
||||
color = (opa << 24) | (opa << 16) | (opa << 8) | opa;
|
||||
}
|
||||
blend = VG_LITE_BLEND_SRC_OVER;
|
||||
src_vgbuf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
|
||||
src_vgbuf.transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
|
||||
}
|
||||
|
||||
err = vg_lite_blit_rect(&dst_vgbuf, &src_vgbuf, rect, &matrix, blend, color, VG_LITE_FILTER_POINT);
|
||||
VG_LITE_ERR_RETURN_INV(err, "Blit rectangle failed.");
|
||||
|
||||
err = vg_lite_finish();
|
||||
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
#if VG_LITE_BLIT_SPLIT_ENABLED
|
||||
|
||||
static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
lv_coord_t w = lv_area_get_width(&blit->src_area);
|
||||
lv_coord_t h = lv_area_get_height(&blit->src_area);
|
||||
|
||||
int32_t srcStridePx = blit->src_stride / (int32_t)sizeof(lv_color_t);
|
||||
int32_t dstStridePx = blit->dst_stride / (int32_t)sizeof(lv_color_t);
|
||||
|
||||
lv_color_t * src = (lv_color_t *)blit->src + blit->src_area.y1 * srcStridePx + blit->src_area.x1;
|
||||
lv_color_t * dst = (lv_color_t *)blit->dst + blit->dst_area.y1 * dstStridePx + blit->dst_area.x1;
|
||||
|
||||
if(blit->opa >= (lv_opa_t)LV_OPA_MAX) {
|
||||
/* simple copy */
|
||||
for(y = 0; y < h; y++) {
|
||||
lv_memcpy(dst, src, (uint32_t)w * sizeof(lv_color_t));
|
||||
src += srcStridePx;
|
||||
dst += dstStridePx;
|
||||
}
|
||||
}
|
||||
else if(blit->opa >= LV_OPA_MIN) {
|
||||
/* alpha blending */
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
dst[x] = lv_color_mix(src[x], dst[x], blit->opa);
|
||||
}
|
||||
src += srcStridePx;
|
||||
dst += dstStridePx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit)
|
||||
{
|
||||
|
||||
/* Test for minimal width */
|
||||
if(lv_area_get_width(&blit->src_area) < (lv_coord_t)LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX)
|
||||
VG_LITE_RETURN_INV("Src area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->src_area),
|
||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
||||
|
||||
/* Test for minimal width */
|
||||
if(lv_area_get_width(&blit->dst_area) < (lv_coord_t)LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX)
|
||||
VG_LITE_RETURN_INV("Dest area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->dst_area),
|
||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
||||
|
||||
/* Test for pointer alignment */
|
||||
if((((uintptr_t) blit->src) % LV_ATTRIBUTE_MEM_ALIGN_SIZE) != 0x0)
|
||||
VG_LITE_RETURN_INV("Src buffer ptr (0x%X) not aligned to %d.", (size_t) blit->src, LV_ATTRIBUTE_MEM_ALIGN_SIZE);
|
||||
|
||||
/* No alignment requirement for destination pixel buffer when using mode VG_LITE_LINEAR */
|
||||
|
||||
/* Test for stride alignment */
|
||||
if((blit->src_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != 0x0)
|
||||
VG_LITE_RETURN_INV("Src buffer stride (%d px) not aligned to %d px.", blit->src_stride,
|
||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
||||
|
||||
/* Test for stride alignment */
|
||||
if((blit->dst_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != 0x0)
|
||||
VG_LITE_RETURN_INV("Dest buffer stride (%d px) not aligned to %d px.", blit->dst_stride,
|
||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
||||
|
||||
if((lv_area_get_width(&blit->src_area) != lv_area_get_width(&blit->dst_area)) ||
|
||||
(lv_area_get_height(&blit->src_area) != lv_area_get_height(&blit->dst_area)))
|
||||
VG_LITE_RETURN_INV("Src and dest buffer areas are not equal.");
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static void _align_x(lv_area_t * area, lv_color_t ** buf)
|
||||
{
|
||||
|
||||
int alignedAreaStartPx = area->x1 - (area->x1 % (LV_ATTRIBUTE_MEM_ALIGN_SIZE * 8 / LV_COLOR_DEPTH));
|
||||
VG_LITE_COND_STOP(alignedAreaStartPx < 0, "Negative X alignment.");
|
||||
|
||||
area->x1 -= alignedAreaStartPx;
|
||||
area->x2 -= alignedAreaStartPx;
|
||||
*buf += alignedAreaStartPx;
|
||||
}
|
||||
|
||||
static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx)
|
||||
{
|
||||
int LineToAlignMem;
|
||||
int alignedAreaStartPy;
|
||||
/* find how many lines of pixels will respect memory alignment requirement */
|
||||
if(stridePx % (uint32_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE == 0U) {
|
||||
alignedAreaStartPy = area->y1;
|
||||
}
|
||||
else {
|
||||
LineToAlignMem = LV_ATTRIBUTE_MEM_ALIGN_SIZE / (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
||||
VG_LITE_COND_STOP(LV_ATTRIBUTE_MEM_ALIGN_SIZE % (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX),
|
||||
"Complex case: need gcd function.");
|
||||
alignedAreaStartPy = area->y1 - (area->y1 % LineToAlignMem);
|
||||
VG_LITE_COND_STOP(alignedAreaStartPy < 0, "Negative Y alignment.");
|
||||
}
|
||||
|
||||
area->y1 -= alignedAreaStartPy;
|
||||
area->y2 -= alignedAreaStartPy;
|
||||
*buf += (uint32_t)alignedAreaStartPy * stridePx;
|
||||
}
|
||||
#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_blend.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2020-2022 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_DRAW_VGLITE_BLEND_H
|
||||
#define LV_DRAW_VGLITE_BLEND_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
#include "lv_gpu_nxp_vglite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#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 5000
|
||||
#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 5000
|
||||
#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 5000
|
||||
#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 5000
|
||||
#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 5000
|
||||
#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*/
|
||||
int32_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*/
|
||||
int32_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)*/
|
||||
uint32_t angle; /**< Rotation angle (1/10 of degree)*/
|
||||
uint32_t zoom; /**< 256 = no zoom (1:1 scale ratio)*/
|
||||
lv_point_t pivot; /**< The coordinates of rotation pivot in source image buffer*/
|
||||
} lv_gpu_nxp_vglite_blit_info_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Fill area, with optional opacity.
|
||||
*
|
||||
* @param[in/out] 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);
|
||||
|
||||
/**
|
||||
* BLock Image Transfer with transformation.
|
||||
*
|
||||
* @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_transform(lv_gpu_nxp_vglite_blit_info_t * blit);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_VGLITE_BLEND_H*/
|
||||
@@ -0,0 +1,244 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_rect.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2021, 2022 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_vglite_rect.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
vg_lite_buffer_t vgbuf;
|
||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||
lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area);
|
||||
lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area);
|
||||
vg_lite_path_t path;
|
||||
vg_lite_color_t vgcol; /* vglite takes ABGR */
|
||||
vg_lite_matrix_t matrix;
|
||||
lv_coord_t width = lv_area_get_width(coords);
|
||||
lv_coord_t height = lv_area_get_height(coords);
|
||||
vg_lite_linear_gradient_t gradient;
|
||||
vg_lite_matrix_t * grad_matrix;
|
||||
|
||||
if(dsc->radius < 0)
|
||||
return LV_RES_INV;
|
||||
|
||||
/* Make areas relative to draw buffer */
|
||||
lv_area_t rel_coords;
|
||||
lv_area_copy(&rel_coords, coords);
|
||||
lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||
|
||||
lv_area_t rel_clip;
|
||||
lv_area_copy(&rel_clip, draw_ctx->clip_area);
|
||||
lv_area_move(&rel_clip, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||
|
||||
/*** Init destination buffer ***/
|
||||
if(lv_vglite_init_buf(&vgbuf, (uint32_t)dest_width, (uint32_t)dest_height, (uint32_t)dest_width * sizeof(lv_color_t),
|
||||
(const lv_color_t *)draw_ctx->buf, false) != LV_RES_OK)
|
||||
VG_LITE_RETURN_INV("Init buffer failed.");
|
||||
|
||||
/*** Init path ***/
|
||||
int32_t rad = dsc->radius;
|
||||
if(dsc->radius == LV_RADIUS_CIRCLE) {
|
||||
rad = (width > height) ? height / 2 : width / 2;
|
||||
}
|
||||
|
||||
if((dsc->radius == LV_RADIUS_CIRCLE) && (width == height)) {
|
||||
float tang = ((float)rad * BEZIER_OPTIM_CIRCLE);
|
||||
int32_t cpoff = (int32_t)tang;
|
||||
int32_t circle_path[] = { /*VG circle path*/
|
||||
VLC_OP_MOVE, rel_coords.x1 + rad, rel_coords.y1,
|
||||
VLC_OP_CUBIC_REL, cpoff, 0, rad, rad - cpoff, rad, rad, /* top-right */
|
||||
VLC_OP_CUBIC_REL, 0, cpoff, cpoff - rad, rad, 0 - rad, rad, /* bottom-right */
|
||||
VLC_OP_CUBIC_REL, 0 - cpoff, 0, 0 - rad, cpoff - rad, 0 - rad, 0 - rad, /* bottom-left */
|
||||
VLC_OP_CUBIC_REL, 0, 0 - cpoff, rad - cpoff, 0 - rad, rad, 0 - rad, /* top-left */
|
||||
VLC_OP_END
|
||||
};
|
||||
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(circle_path), circle_path,
|
||||
(vg_lite_float_t) rel_clip.x1, (vg_lite_float_t) rel_clip.y1,
|
||||
((vg_lite_float_t) rel_clip.x2) + 1.0f, ((vg_lite_float_t) rel_clip.y2) + 1.0f);
|
||||
}
|
||||
else if(dsc->radius > 0) {
|
||||
float tang = ((float)rad * BEZIER_OPTIM_CIRCLE);
|
||||
int32_t cpoff = (int32_t)tang;
|
||||
int32_t rounded_path[] = { /*VG rounded rectangular path*/
|
||||
VLC_OP_MOVE, rel_coords.x1 + rad, rel_coords.y1,
|
||||
VLC_OP_LINE, rel_coords.x2 - rad + 1, rel_coords.y1, /* top */
|
||||
VLC_OP_CUBIC_REL, cpoff, 0, rad, rad - cpoff, rad, rad, /* top-right */
|
||||
VLC_OP_LINE, rel_coords.x2 + 1, rel_coords.y2 - rad + 1, /* right */
|
||||
VLC_OP_CUBIC_REL, 0, cpoff, cpoff - rad, rad, 0 - rad, rad, /* bottom-right */
|
||||
VLC_OP_LINE, rel_coords.x1 + rad, rel_coords.y2 + 1, /* bottom */
|
||||
VLC_OP_CUBIC_REL, 0 - cpoff, 0, 0 - rad, cpoff - rad, 0 - rad, 0 - rad, /* bottom-left */
|
||||
VLC_OP_LINE, rel_coords.x1, rel_coords.y1 + rad, /* left */
|
||||
VLC_OP_CUBIC_REL, 0, 0 - cpoff, rad - cpoff, 0 - rad, rad, 0 - rad, /* top-left */
|
||||
VLC_OP_END
|
||||
};
|
||||
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(rounded_path), rounded_path,
|
||||
(vg_lite_float_t) rel_clip.x1, (vg_lite_float_t) rel_clip.y1,
|
||||
((vg_lite_float_t) rel_clip.x2) + 1.0f, ((vg_lite_float_t) rel_clip.y2) + 1.0f);
|
||||
}
|
||||
else {
|
||||
int32_t rect_path[] = { /*VG rectangular path*/
|
||||
VLC_OP_MOVE, rel_coords.x1, rel_coords.y1,
|
||||
VLC_OP_LINE, rel_coords.x2 + 1, rel_coords.y1,
|
||||
VLC_OP_LINE, rel_coords.x2 + 1, rel_coords.y2 + 1,
|
||||
VLC_OP_LINE, rel_coords.x1, rel_coords.y2 + 1,
|
||||
VLC_OP_LINE, rel_coords.x1, rel_coords.y1,
|
||||
VLC_OP_END
|
||||
};
|
||||
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_LOW, sizeof(rect_path), rect_path,
|
||||
(vg_lite_float_t) rel_clip.x1, (vg_lite_float_t) rel_clip.y1,
|
||||
((vg_lite_float_t) rel_clip.x2) + 1.0f, ((vg_lite_float_t) rel_clip.y2) + 1.0f);
|
||||
}
|
||||
|
||||
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
|
||||
vg_lite_identity(&matrix);
|
||||
|
||||
/*** Init Color/Gradient ***/
|
||||
if(dsc->bg_grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE) {
|
||||
uint32_t colors[2];
|
||||
uint32_t stops[2];
|
||||
lv_color32_t col32[2];
|
||||
|
||||
/* Gradient setup */
|
||||
uint8_t cnt = MAX(dsc->bg_grad.stops_count, 2);
|
||||
for(uint8_t i = 0; i < cnt; i++) {
|
||||
col32[i].full = lv_color_to32(dsc->bg_grad.stops[i].color); /*Convert color to RGBA8888*/
|
||||
stops[i] = dsc->bg_grad.stops[i].frac;
|
||||
#if LV_COLOR_DEPTH==16
|
||||
colors[i] = ((uint32_t)col32[i].ch.alpha << 24) | ((uint32_t)col32[i].ch.blue << 16) |
|
||||
((uint32_t)col32[i].ch.green << 8) | (uint32_t)col32[i].ch.red;
|
||||
#else /*LV_COLOR_DEPTH==32*/
|
||||
/* watchout: red and blue color components are inverted versus vg_lite_color_t order */
|
||||
colors[i] = ((uint32_t)col32[i].ch.alpha << 24) | ((uint32_t)col32[i].ch.red << 16) |
|
||||
((uint32_t)col32[i].ch.green << 8) | (uint32_t)col32[i].ch.blue;
|
||||
#endif
|
||||
}
|
||||
|
||||
lv_memset_00(&gradient, sizeof(vg_lite_linear_gradient_t));
|
||||
|
||||
err = vg_lite_init_grad(&gradient);
|
||||
VG_LITE_ERR_RETURN_INV(err, "Init gradient failed");
|
||||
|
||||
err = vg_lite_set_grad(&gradient, cnt, colors, stops);
|
||||
VG_LITE_ERR_RETURN_INV(err, "Set gradient failed.");
|
||||
|
||||
err = vg_lite_update_grad(&gradient);
|
||||
VG_LITE_ERR_RETURN_INV(err, "Update gradient failed.");
|
||||
|
||||
grad_matrix = vg_lite_get_grad_matrix(&gradient);
|
||||
vg_lite_identity(grad_matrix);
|
||||
vg_lite_translate((float)rel_coords.x1, (float)rel_coords.y1, grad_matrix);
|
||||
|
||||
if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_VER) {
|
||||
vg_lite_scale(1.0f, (float)height / 256.0f, grad_matrix);
|
||||
vg_lite_rotate(90.0f, grad_matrix);
|
||||
}
|
||||
else { /*LV_GRAD_DIR_HOR*/
|
||||
vg_lite_scale((float)width / 256.0f, 1.0f, grad_matrix);
|
||||
}
|
||||
}
|
||||
|
||||
lv_opa_t bg_opa = dsc->bg_opa;
|
||||
lv_color32_t bg_col32 = {.full = lv_color_to32(dsc->bg_color)}; /*Convert color to RGBA8888*/
|
||||
if(bg_opa <= (lv_opa_t)LV_OPA_MAX) {
|
||||
/* Only pre-multiply color if hardware pre-multiplication is not present */
|
||||
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
|
||||
bg_col32.ch.red = (uint8_t)(((uint16_t)bg_col32.ch.red * bg_opa) >> 8);
|
||||
bg_col32.ch.green = (uint8_t)(((uint16_t)bg_col32.ch.green * bg_opa) >> 8);
|
||||
bg_col32.ch.blue = (uint8_t)(((uint16_t)bg_col32.ch.blue * bg_opa) >> 8);
|
||||
}
|
||||
bg_col32.ch.alpha = bg_opa;
|
||||
}
|
||||
|
||||
#if LV_COLOR_DEPTH==16
|
||||
vgcol = bg_col32.full;
|
||||
#else /*LV_COLOR_DEPTH==32*/
|
||||
vgcol = ((uint32_t)bg_col32.ch.alpha << 24) | ((uint32_t)bg_col32.ch.blue << 16) |
|
||||
((uint32_t)bg_col32.ch.green << 8) | (uint32_t)bg_col32.ch.red;
|
||||
#endif
|
||||
|
||||
/*Clean & invalidate cache*/
|
||||
lv_vglite_invalidate_cache();
|
||||
|
||||
/*** Draw rectangle ***/
|
||||
if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE) {
|
||||
err = vg_lite_draw(&vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
|
||||
}
|
||||
else {
|
||||
err = vg_lite_draw_gradient(&vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient, VG_LITE_BLEND_SRC_OVER);
|
||||
}
|
||||
VG_LITE_ERR_RETURN_INV(err, "Draw gradient failed.");
|
||||
|
||||
err = vg_lite_finish();
|
||||
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
|
||||
|
||||
err = vg_lite_clear_path(&path);
|
||||
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
|
||||
|
||||
if(dsc->bg_grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE) {
|
||||
err = vg_lite_clear_grad(&gradient);
|
||||
VG_LITE_ERR_RETURN_INV(err, "Clear gradient failed.");
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_rect.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2021, 2022 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_DRAW_VGLITE_RECT_H
|
||||
#define LV_DRAW_VGLITE_RECT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
#include "lv_gpu_nxp_vglite.h"
|
||||
#include "../../lv_draw_rect.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Draw rectangle shape with effects (rounded corners, gradient)
|
||||
*
|
||||
* @param draw_ctx drawing context
|
||||
* @param dsc description of the rectangle
|
||||
* @param coords the area where rectangle is clipped
|
||||
*/
|
||||
lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_VGLITE_RECT_H*/
|
||||
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* @file lv_gpu_nxp_vglite.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2020-2022 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_gpu_nxp_vglite.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
#include "../../../core/lv_refr.h"
|
||||
#if BLIT_DBG_AREAS
|
||||
#include "lv_draw_vglite_blend.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if LV_COLOR_DEPTH==16
|
||||
#define VG_LITE_PX_FMT VG_LITE_RGB565
|
||||
#elif LV_COLOR_DEPTH==32
|
||||
#define VG_LITE_PX_FMT VG_LITE_BGRA8888
|
||||
#else
|
||||
#error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32.
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_res_t lv_vglite_init_buf(vg_lite_buffer_t * vgbuf, uint32_t width, uint32_t height, uint32_t stride,
|
||||
const lv_color_t * ptr, bool source)
|
||||
{
|
||||
/*Test for memory alignment*/
|
||||
if((((uintptr_t)ptr) % (uintptr_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE) != (uintptr_t)0x0U)
|
||||
VG_LITE_RETURN_INV("%s buffer (0x%x) not aligned to %d.", source ? "Src" : "Dest",
|
||||
(size_t) ptr, LV_ATTRIBUTE_MEM_ALIGN_SIZE);
|
||||
|
||||
/*Test for stride alignment*/
|
||||
if(source && (stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t))) != 0x0U)
|
||||
VG_LITE_RETURN_INV("Src buffer stride (%d bytes) not aligned to %d bytes.", stride,
|
||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t));
|
||||
|
||||
vgbuf->format = VG_LITE_PX_FMT;
|
||||
vgbuf->tiled = VG_LITE_LINEAR;
|
||||
vgbuf->image_mode = VG_LITE_NORMAL_IMAGE_MODE;
|
||||
vgbuf->transparency_mode = VG_LITE_IMAGE_OPAQUE;
|
||||
|
||||
vgbuf->width = (int32_t)width;
|
||||
vgbuf->height = (int32_t)height;
|
||||
vgbuf->stride = (int32_t)stride;
|
||||
|
||||
lv_memset_00(&vgbuf->yuv, sizeof(vgbuf->yuv));
|
||||
|
||||
vgbuf->memory = (void *)ptr;
|
||||
vgbuf->address = (uint32_t)vgbuf->memory;
|
||||
vgbuf->handle = NULL;
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
#if BLIT_DBG_AREAS
|
||||
void lv_vglite_dbg_draw_rectangle(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height,
|
||||
lv_area_t * fill_area, lv_color_t color)
|
||||
{
|
||||
lv_area_t a;
|
||||
|
||||
/* top line */
|
||||
a.x1 = fill_area->x1;
|
||||
a.x2 = fill_area->x2;
|
||||
a.y1 = fill_area->y1;
|
||||
a.y2 = fill_area->y1;
|
||||
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
|
||||
|
||||
|
||||
/* bottom line */
|
||||
a.x1 = fill_area->x1;
|
||||
a.x2 = fill_area->x2;
|
||||
a.y1 = fill_area->y2;
|
||||
a.y2 = fill_area->y2;
|
||||
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
|
||||
|
||||
/* left line */
|
||||
a.x1 = fill_area->x1;
|
||||
a.x2 = fill_area->x1;
|
||||
a.y1 = fill_area->y1;
|
||||
a.y2 = fill_area->y2;
|
||||
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
|
||||
|
||||
/* right line */
|
||||
a.x1 = fill_area->x2;
|
||||
a.x2 = fill_area->x2;
|
||||
a.y1 = fill_area->y1;
|
||||
a.y2 = fill_area->y2;
|
||||
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
|
||||
}
|
||||
#endif /* BLIT_DBG_AREAS */
|
||||
|
||||
void lv_vglite_invalidate_cache(void)
|
||||
{
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
if(disp->driver->clean_dcache_cb)
|
||||
disp->driver->clean_dcache_cb(disp->driver);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
* @file lv_gpu_nxp_vglite.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright 2020-2022 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_GPU_NXP_VGLITE_H
|
||||
#define LV_GPU_NXP_VGLITE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
#include "vg_lite.h"
|
||||
#include "../../sw/lv_draw_sw.h"
|
||||
#include "../../../misc/lv_log.h"
|
||||
#include "fsl_debug_console.h"
|
||||
|
||||
/*********************
|
||||
* 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_LOG_ERRORS
|
||||
/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR)*/
|
||||
#define LV_GPU_NXP_VG_LITE_LOG_ERRORS 1
|
||||
#endif
|
||||
|
||||
#ifndef LV_GPU_NXP_VG_LITE_LOG_TRACES
|
||||
/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR)*/
|
||||
#define LV_GPU_NXP_VG_LITE_LOG_TRACES 0
|
||||
#endif
|
||||
|
||||
/* Draw rectangles around BLIT tiles */
|
||||
#define BLIT_DBG_AREAS 0
|
||||
|
||||
/* Print detailed info to SDK console (NOT to LVGL log system) */
|
||||
#define BLIT_DBG_VERBOSE 0
|
||||
|
||||
/* Verbose debug print */
|
||||
#if BLIT_DBG_VERBOSE
|
||||
#define PRINT_BLT PRINTF
|
||||
#else
|
||||
#define PRINT_BLT(...)
|
||||
#endif
|
||||
|
||||
/* The optimal Bezier control point offset for radial unit
|
||||
* see: https://spencermortensen.com/articles/bezier-circle/
|
||||
**/
|
||||
#define BEZIER_OPTIM_CIRCLE 0.551915024494f
|
||||
|
||||
/* Draw lines for control points of Bezier curves */
|
||||
#define BEZIER_DBG_CONTROL_POINTS 0
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Fills vg_lite_buffer_t structure according given parameters.
|
||||
*
|
||||
* @param[in/out] vgbuf Buffer structure to be filled
|
||||
* @param[in] width Width of buffer in pixels
|
||||
* @param[in] height Height of buffer in pixels
|
||||
* @param[in] stride Stride of the buffer in bytes
|
||||
* @param[in] ptr Pointer to the buffer (must be aligned according VG-Lite requirements)
|
||||
* @param[in] source Boolean to check if this is a source buffer
|
||||
*/
|
||||
lv_res_t lv_vglite_init_buf(vg_lite_buffer_t * vgbuf, uint32_t width, uint32_t height, uint32_t stride,
|
||||
const lv_color_t * ptr, bool source);
|
||||
|
||||
#if BLIT_DBG_AREAS
|
||||
/**
|
||||
* Draw a simple rectangle, 1 px line width.
|
||||
*
|
||||
* @param dest_buf Destination buffer
|
||||
* @param dest_width Destination buffer width (must be aligned on 16px)
|
||||
* @param dest_height Destination buffer height
|
||||
* @param fill_area Rectangle coordinates
|
||||
* @param color Rectangle color
|
||||
*/
|
||||
void lv_vglite_dbg_draw_rectangle(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height,
|
||||
lv_area_t * fill_area, lv_color_t color);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Clean & invalidate cache.
|
||||
*/
|
||||
void lv_vglite_invalidate_cache(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#define VG_LITE_COND_STOP(cond, txt) \
|
||||
do { \
|
||||
if (cond) { \
|
||||
LV_LOG_ERROR("%s. STOP!", txt); \
|
||||
for ( ; ; ); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
#define VG_LITE_ERR_RETURN_INV(err, fmt, ...) \
|
||||
do { \
|
||||
if(err != VG_LITE_SUCCESS) { \
|
||||
LV_LOG_ERROR(fmt, ##__VA_ARGS__); \
|
||||
return LV_RES_INV; \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define VG_LITE_ERR_RETURN_INV(err, fmt, ...) \
|
||||
do { \
|
||||
if(err != VG_LITE_SUCCESS) { \
|
||||
return LV_RES_INV; \
|
||||
} \
|
||||
}while(0)
|
||||
#endif /*LV_GPU_NXP_VG_LITE_LOG_ERRORS*/
|
||||
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_TRACES
|
||||
#define VG_LITE_LOG_TRACE(fmt, ...) \
|
||||
do { \
|
||||
LV_LOG_ERROR(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define VG_LITE_RETURN_INV(fmt, ...) \
|
||||
do { \
|
||||
LV_LOG_ERROR(fmt, ##__VA_ARGS__); \
|
||||
return LV_RES_INV; \
|
||||
} while (0)
|
||||
#else
|
||||
#define VG_LITE_LOG_TRACE(fmt, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define VG_LITE_RETURN_INV(fmt, ...) \
|
||||
do { \
|
||||
return LV_RES_INV; \
|
||||
}while(0)
|
||||
#endif /*LV_GPU_NXP_VG_LITE_LOG_TRACES*/
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GPU_NXP_VGLITE_H*/
|
||||
@@ -0,0 +1,28 @@
|
||||
# SDL_Renderer Based Drawing Functions
|
||||
|
||||
In LVGL, drawing was performed by CPU. To improve drawing performance on platforms with GPU,
|
||||
we should perform drawing operations on GPU if possible.
|
||||
|
||||
This implementation has moved most bitmap blending and drawing procedures to utilize SDL_Renderer,
|
||||
which takes advantages of hardware acceleration APIs like DirectX or OpenGL.
|
||||
|
||||
This implementation can be also considered as a reference implementation, for contributors wants to
|
||||
develop accelerated drawing functions with other APIs such as OpenGL/OpenGL ES.
|
||||
|
||||
## Caveats
|
||||
`lv_draw_arc`, `lv_draw_line` is not enabled, due to incomplete implementation. So lines and arcs will
|
||||
have significant impact to drawing performances.
|
||||
|
||||
Performance of this implementation still has room to improve. Or we should use more powerful APIs
|
||||
such as OpenGL.
|
||||
|
||||
## Notices for files
|
||||
|
||||
### `lv_draw_sdl_stack_blur.c`
|
||||
|
||||
Contains modified code from [android-stackblur](https://github.com/kikoso/android-stackblur) project.
|
||||
Apache License 2.0
|
||||
|
||||
### `lv_draw_sdl_lru.c`/`lv_draw_sdl_lru.h`
|
||||
|
||||
Contains modified code from [C-LRU-Cache](https://github.com/willcannings/C-LRU-Cache) project. No license defined.
|
||||
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @file lv_draw_sdl.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
void lv_draw_sdl_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
lv_res_t lv_draw_sdl_img_core(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords, const void * src);
|
||||
|
||||
void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
|
||||
uint32_t letter);
|
||||
|
||||
void lv_draw_sdl_draw_line(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_sdl_draw_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_sdl_polygon(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_sdl_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_init_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
_lv_draw_sdl_utils_init();
|
||||
lv_memset_00(draw_ctx, sizeof(lv_draw_sdl_ctx_t));
|
||||
draw_ctx->draw_rect = lv_draw_sdl_draw_rect;
|
||||
draw_ctx->draw_img = lv_draw_sdl_img_core;
|
||||
draw_ctx->draw_letter = lv_draw_sdl_draw_letter;
|
||||
draw_ctx->draw_line = lv_draw_sdl_draw_line;
|
||||
draw_ctx->draw_arc = lv_draw_sdl_draw_arc;
|
||||
draw_ctx->draw_polygon = lv_draw_sdl_polygon;
|
||||
draw_ctx->draw_bg = lv_draw_sdl_draw_bg;
|
||||
draw_ctx->layer_init = lv_draw_sdl_layer_init;
|
||||
draw_ctx->layer_blend = lv_draw_sdl_layer_blend;
|
||||
draw_ctx->layer_destroy = lv_draw_sdl_layer_destroy;
|
||||
draw_ctx->layer_instance_size = sizeof(lv_draw_sdl_layer_ctx_t);
|
||||
lv_draw_sdl_ctx_t * draw_ctx_sdl = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
draw_ctx_sdl->renderer = ((lv_draw_sdl_drv_param_t *) disp_drv->user_data)->renderer;
|
||||
draw_ctx_sdl->internals = lv_mem_alloc(sizeof(lv_draw_sdl_context_internals_t));
|
||||
lv_memset_00(draw_ctx_sdl->internals, sizeof(lv_draw_sdl_context_internals_t));
|
||||
lv_draw_sdl_texture_cache_init(draw_ctx_sdl);
|
||||
}
|
||||
|
||||
void lv_draw_sdl_deinit_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
lv_draw_sdl_ctx_t * draw_ctx_sdl = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
lv_draw_sdl_texture_cache_deinit(draw_ctx_sdl);
|
||||
lv_mem_free(draw_ctx_sdl->internals);
|
||||
_lv_draw_sdl_utils_deinit();
|
||||
}
|
||||
|
||||
SDL_Texture * lv_draw_sdl_create_screen_texture(SDL_Renderer * renderer, lv_coord_t hor, lv_coord_t ver)
|
||||
{
|
||||
SDL_Texture * texture = SDL_CreateTexture(renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET, hor, ver);
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -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*/
|
||||
@@ -0,0 +1,19 @@
|
||||
CSRCS += lv_draw_sdl.c
|
||||
CSRCS += lv_draw_sdl_arc.c
|
||||
CSRCS += lv_draw_sdl_bg.c
|
||||
CSRCS += lv_draw_sdl_composite.c
|
||||
CSRCS += lv_draw_sdl_img.c
|
||||
CSRCS += lv_draw_sdl_label.c
|
||||
CSRCS += lv_draw_sdl_line.c
|
||||
CSRCS += lv_draw_sdl_mask.c
|
||||
CSRCS += lv_draw_sdl_polygon.c
|
||||
CSRCS += lv_draw_sdl_rect.c
|
||||
CSRCS += lv_draw_sdl_stack_blur.c
|
||||
CSRCS += lv_draw_sdl_texture_cache.c
|
||||
CSRCS += lv_draw_sdl_utils.c
|
||||
CSRCS += lv_draw_sdl_layer.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl"
|
||||
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_arc.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords, const int16_t * ids, int16_t ids_count,
|
||||
const int16_t * caps);
|
||||
|
||||
static void get_cap_area(int16_t angle, lv_coord_t thickness, uint16_t radius, const lv_point_t * center,
|
||||
lv_area_t * out);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
void lv_draw_sdl_draw_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)
|
||||
{
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
|
||||
lv_area_t area_out;
|
||||
area_out.x1 = center->x - radius;
|
||||
area_out.y1 = center->y - radius;
|
||||
area_out.x2 = center->x + radius - 1; /*-1 because the center already belongs to the left/bottom part*/
|
||||
area_out.y2 = center->y + radius - 1;
|
||||
|
||||
lv_area_t draw_area;
|
||||
if(!_lv_area_intersect(&draw_area, &area_out, draw_ctx->clip_area)) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_area_t area_in;
|
||||
lv_area_copy(&area_in, &area_out);
|
||||
area_in.x1 += dsc->width;
|
||||
area_in.y1 += dsc->width;
|
||||
area_in.x2 -= dsc->width;
|
||||
area_in.y2 -= dsc->width;
|
||||
|
||||
|
||||
while(start_angle >= 360) start_angle -= 360;
|
||||
while(end_angle >= 360) end_angle -= 360;
|
||||
|
||||
int16_t mask_ids[3] = {LV_MASK_ID_INV, LV_MASK_ID_INV, LV_MASK_ID_INV}, mask_ids_count = 1;
|
||||
int16_t cap_ids[2] = {LV_MASK_ID_INV, LV_MASK_ID_INV};
|
||||
|
||||
lv_draw_mask_radius_param_t mask_out_param;
|
||||
lv_draw_mask_radius_init(&mask_out_param, &area_out, LV_RADIUS_CIRCLE, false);
|
||||
mask_ids[0] = lv_draw_mask_add(&mask_out_param, NULL);
|
||||
|
||||
lv_draw_mask_radius_param_t mask_in_param;
|
||||
if(lv_area_get_width(&area_in) > 0 && lv_area_get_height(&area_in) > 0) {
|
||||
lv_draw_mask_radius_init(&mask_in_param, &area_in, LV_RADIUS_CIRCLE, true);
|
||||
mask_ids[1] = lv_draw_mask_add(&mask_in_param, NULL);
|
||||
mask_ids_count++;
|
||||
}
|
||||
|
||||
lv_draw_mask_angle_param_t mask_angle_param;
|
||||
if((start_angle - end_angle) % 360) {
|
||||
lv_draw_mask_angle_init(&mask_angle_param, center->x, center->y, start_angle, end_angle);
|
||||
mask_ids[2] = lv_draw_mask_add(&mask_angle_param, NULL);
|
||||
mask_ids_count++;
|
||||
}
|
||||
|
||||
lv_draw_mask_radius_param_t cap_start_param, cap_end_param;
|
||||
if(mask_ids_count == 3 && dsc->rounded) {
|
||||
lv_area_t start_area, end_area;
|
||||
get_cap_area((int16_t) start_angle, dsc->width, radius, center, &start_area);
|
||||
get_cap_area((int16_t) end_angle, dsc->width, radius, center, &end_area);
|
||||
lv_draw_mask_radius_init(&cap_start_param, &start_area, dsc->width / 2, false);
|
||||
cap_ids[0] = lv_draw_mask_add(&cap_start_param, NULL);
|
||||
lv_draw_mask_radius_init(&cap_end_param, &end_area, dsc->width / 2, false);
|
||||
cap_ids[1] = lv_draw_mask_add(&cap_end_param, NULL);
|
||||
}
|
||||
|
||||
lv_coord_t w = lv_area_get_width(&draw_area), h = lv_area_get_height(&draw_area);
|
||||
SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h);
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
dump_masks(texture, &draw_area, mask_ids, mask_ids_count, cap_ids[0] != LV_MASK_ID_INV ? cap_ids : NULL);
|
||||
|
||||
lv_draw_mask_remove_id(mask_ids[0]);
|
||||
lv_draw_mask_free_param(&mask_out_param);
|
||||
|
||||
if(mask_ids_count > 1) {
|
||||
lv_draw_mask_remove_id(mask_ids[1]);
|
||||
lv_draw_mask_free_param(&mask_in_param);
|
||||
}
|
||||
|
||||
if(mask_ids_count > 2) {
|
||||
lv_draw_mask_remove_id(mask_ids[2]);
|
||||
lv_draw_mask_free_param(&mask_angle_param);
|
||||
}
|
||||
|
||||
if(cap_ids[0] != LV_MASK_ID_INV) {
|
||||
lv_draw_mask_remove_id(cap_ids[0]);
|
||||
lv_draw_mask_remove_id(cap_ids[1]);
|
||||
lv_draw_mask_free_param(&cap_start_param);
|
||||
lv_draw_mask_free_param(&cap_end_param);
|
||||
}
|
||||
|
||||
SDL_Rect srcrect = {0, 0, w, h}, dstrect;
|
||||
lv_area_to_sdl_rect(&draw_area, &dstrect);
|
||||
SDL_Color color;
|
||||
lv_color_to_sdl_color(&dsc->color, &color);
|
||||
SDL_SetTextureColorMod(texture, color.r, color.g, color.b);
|
||||
SDL_SetTextureAlphaMod(texture, dsc->opa);
|
||||
SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords, const int16_t * ids, int16_t ids_count,
|
||||
const int16_t * caps)
|
||||
{
|
||||
lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
SDL_assert(w > 0 && h > 0);
|
||||
SDL_Rect rect = {0, 0, w, h};
|
||||
uint8_t * pixels;
|
||||
int pitch;
|
||||
if(SDL_LockTexture(texture, &rect, (void **) &pixels, &pitch) != 0) return;
|
||||
|
||||
lv_opa_t * line_buf = lv_mem_buf_get(rect.w);
|
||||
for(lv_coord_t y = 0; y < rect.h; y++) {
|
||||
lv_memset_ff(line_buf, rect.w);
|
||||
lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) rect.w;
|
||||
lv_draw_mask_res_t res;
|
||||
res = lv_draw_mask_apply_ids(line_buf, abs_x, abs_y, len, ids, ids_count);
|
||||
if(res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_memset_00(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else if(res == LV_DRAW_MASK_RES_FULL_COVER) {
|
||||
lv_memset_ff(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else {
|
||||
for(int x = 0; x < rect.w; x++) {
|
||||
uint8_t * pixel = &pixels[y * pitch + x * 4];
|
||||
*pixel = line_buf[x];
|
||||
pixel[1] = pixel[2] = pixel[3] = 0xFF;
|
||||
}
|
||||
}
|
||||
if(caps) {
|
||||
for(int i = 0; i < 2; i++) {
|
||||
lv_memset_ff(line_buf, rect.w);
|
||||
res = lv_draw_mask_apply_ids(line_buf, abs_x, abs_y, len, &caps[i], 1);
|
||||
if(res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
/* Ignore */
|
||||
}
|
||||
else if(res == LV_DRAW_MASK_RES_FULL_COVER) {
|
||||
lv_memset_ff(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else {
|
||||
for(int x = 0; x < rect.w; x++) {
|
||||
uint8_t * pixel = &pixels[y * pitch + x * 4];
|
||||
uint16_t old_opa = line_buf[x] + *pixel;
|
||||
*pixel = LV_MIN(old_opa, 0xFF);
|
||||
pixel[1] = pixel[2] = pixel[3] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lv_mem_buf_release(line_buf);
|
||||
SDL_UnlockTexture(texture);
|
||||
}
|
||||
|
||||
static void get_cap_area(int16_t angle, lv_coord_t thickness, uint16_t radius, const lv_point_t * center,
|
||||
lv_area_t * out)
|
||||
{
|
||||
const uint8_t ps = 8;
|
||||
const uint8_t pa = 127;
|
||||
|
||||
int32_t thick_half = thickness / 2;
|
||||
uint8_t thick_corr = (thickness & 0x01) ? 0 : 1;
|
||||
|
||||
int32_t cir_x;
|
||||
int32_t cir_y;
|
||||
|
||||
cir_x = ((radius - thick_half) * lv_trigo_sin((int16_t)(90 - angle))) >> (LV_TRIGO_SHIFT - ps);
|
||||
cir_y = ((radius - thick_half) * lv_trigo_sin(angle)) >> (LV_TRIGO_SHIFT - ps);
|
||||
|
||||
/*Actually the center of the pixel need to be calculated so apply 1/2 px offset*/
|
||||
if(cir_x > 0) {
|
||||
cir_x = (cir_x - pa) >> ps;
|
||||
out->x1 = cir_x - thick_half + thick_corr;
|
||||
out->x2 = cir_x + thick_half;
|
||||
}
|
||||
else {
|
||||
cir_x = (cir_x + pa) >> ps;
|
||||
out->x1 = cir_x - thick_half;
|
||||
out->x2 = cir_x + thick_half - thick_corr;
|
||||
}
|
||||
|
||||
if(cir_y > 0) {
|
||||
cir_y = (cir_y - pa) >> ps;
|
||||
out->y1 = cir_y - thick_half + thick_corr;
|
||||
out->y2 = cir_y + thick_half;
|
||||
}
|
||||
else {
|
||||
cir_y = (cir_y + pa) >> ps;
|
||||
out->y1 = cir_y - thick_half;
|
||||
out->y2 = cir_y + thick_half - thick_corr;
|
||||
}
|
||||
lv_area_move(out, center->x, center->y);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_bg.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../lv_draw_rect.h"
|
||||
#include "../lv_draw_img.h"
|
||||
#include "../lv_draw_label.h"
|
||||
#include "../lv_draw_mask.h"
|
||||
#include "../../core/lv_refr.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
const lv_area_t * clip = draw_ctx->clip_area;
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
/* Coords will be translated so coords will start at (0,0) */
|
||||
lv_area_t t_area;
|
||||
bool has_content = _lv_area_intersect(&t_area, coords, clip);
|
||||
|
||||
/* Shadows and outlines will also draw in extended area */
|
||||
if(has_content) {
|
||||
if(dsc->bg_img_src) {
|
||||
draw_bg_img(ctx, coords, &t_area, dsc);
|
||||
}
|
||||
else {
|
||||
draw_bg_color(ctx, coords, &t_area, dsc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
SDL_Color bg_color;
|
||||
lv_color_to_sdl_color(&dsc->bg_color, &bg_color);
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, bg_color.r, bg_color.g, bg_color.b, dsc->bg_opa);
|
||||
|
||||
SDL_Rect rect;
|
||||
lv_area_to_sdl_rect(draw_area, &rect);
|
||||
SDL_RenderFillRect(ctx->renderer, &rect);
|
||||
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
|
||||
static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, 0, 0, 0, 0);
|
||||
|
||||
SDL_Rect rect;
|
||||
lv_area_to_sdl_rect(draw_area, &rect);
|
||||
SDL_RenderFillRect(ctx->renderer, &rect);
|
||||
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
|
||||
lv_draw_rect((lv_draw_ctx_t *) ctx, dsc, coords);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -0,0 +1,262 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_composite.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../../misc/lv_gc.h"
|
||||
#include "../../core/lv_refr.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_priv.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
lv_draw_sdl_composite_texture_id_t type;
|
||||
} composite_key_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static composite_key_t mask_key_create(lv_draw_sdl_composite_texture_id_t type);
|
||||
|
||||
static lv_coord_t next_pow_of_2(lv_coord_t num);
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
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)
|
||||
{
|
||||
lv_area_t full_coords = *coords_in;
|
||||
|
||||
/* Normalize full_coords */
|
||||
if(full_coords.x1 > full_coords.x2) {
|
||||
lv_coord_t x2 = full_coords.x2;
|
||||
full_coords.x2 = full_coords.x1;
|
||||
full_coords.x1 = x2;
|
||||
}
|
||||
if(full_coords.y1 > full_coords.y2) {
|
||||
lv_coord_t y2 = full_coords.y2;
|
||||
full_coords.y2 = full_coords.y1;
|
||||
full_coords.y1 = y2;
|
||||
}
|
||||
|
||||
if(extension) {
|
||||
full_coords.x1 -= extension->x1;
|
||||
full_coords.x2 += extension->x2;
|
||||
full_coords.y1 -= extension->y1;
|
||||
full_coords.y2 += extension->y2;
|
||||
}
|
||||
|
||||
if(!_lv_area_intersect(apply_area, &full_coords, clip_in)) return false;
|
||||
bool has_mask = lv_draw_mask_is_any(apply_area);
|
||||
|
||||
const bool draw_mask = has_mask && LV_GPU_SDL_CUSTOM_BLEND_MODE;
|
||||
const bool draw_blend = blend_mode != LV_BLEND_MODE_NORMAL;
|
||||
if(draw_mask || draw_blend) {
|
||||
lv_draw_sdl_context_internals_t * internals = ctx->internals;
|
||||
LV_ASSERT(internals->mask == NULL && internals->composition == NULL && internals->target_backup == NULL);
|
||||
|
||||
lv_coord_t w = lv_area_get_width(apply_area), h = lv_area_get_height(apply_area);
|
||||
internals->composition = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0, w, h);
|
||||
/* Don't need to worry about integral overflow */
|
||||
lv_coord_t ofs_x = (lv_coord_t) - apply_area->x1, ofs_y = (lv_coord_t) - apply_area->y1;
|
||||
/* Offset draw area to start with (0,0) of coords */
|
||||
lv_area_move(coords_out, ofs_x, ofs_y);
|
||||
lv_area_move(clip_out, ofs_x, ofs_y);
|
||||
internals->target_backup = SDL_GetRenderTarget(ctx->renderer);
|
||||
SDL_SetRenderTarget(ctx->renderer, internals->composition);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, 255, 255, 255, 0);
|
||||
/* SDL_RenderClear is not working properly, so we overwrite the target with solid color */
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_RenderFillRect(ctx->renderer, NULL);
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
|
||||
#if LV_GPU_SDL_CUSTOM_BLEND_MODE
|
||||
internals->mask = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM0, w, h);
|
||||
dump_masks(internals->mask, apply_area);
|
||||
#endif
|
||||
}
|
||||
else if(has_mask) {
|
||||
/* Fallback mask handling. This will at least make bars looks less bad */
|
||||
for(uint8_t i = 0; i < _LV_MASK_MAX_NUM; i++) {
|
||||
_lv_draw_mask_common_dsc_t * comm_param = LV_GC_ROOT(_lv_draw_mask_list[i]).param;
|
||||
if(comm_param == NULL) continue;
|
||||
switch(comm_param->type) {
|
||||
case LV_DRAW_MASK_TYPE_RADIUS: {
|
||||
const lv_draw_mask_radius_param_t * param = (const lv_draw_mask_radius_param_t *) comm_param;
|
||||
if(param->cfg.outer) break;
|
||||
_lv_area_intersect(clip_out, apply_area, ¶m->cfg.rect);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return has_mask;
|
||||
}
|
||||
|
||||
void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_area, lv_blend_mode_t blend_mode)
|
||||
{
|
||||
lv_draw_sdl_context_internals_t * internals = ctx->internals;
|
||||
SDL_Rect src_rect = {0, 0, lv_area_get_width(apply_area), lv_area_get_height(apply_area)};
|
||||
#if LV_GPU_SDL_CUSTOM_BLEND_MODE
|
||||
if(internals->mask) {
|
||||
SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE,
|
||||
SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_ZERO,
|
||||
SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDOPERATION_ADD);
|
||||
SDL_SetTextureBlendMode(internals->mask, mode);
|
||||
SDL_RenderCopy(ctx->renderer, internals->mask, &src_rect, &src_rect);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Shapes are drawn on composite layer when mask or blend mode is present */
|
||||
if(internals->composition) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(apply_area, &dst_rect);
|
||||
|
||||
SDL_SetRenderTarget(ctx->renderer, internals->target_backup);
|
||||
switch(blend_mode) {
|
||||
case LV_BLEND_MODE_NORMAL:
|
||||
SDL_SetTextureBlendMode(internals->composition, SDL_BLENDMODE_BLEND);
|
||||
break;
|
||||
case LV_BLEND_MODE_ADDITIVE:
|
||||
SDL_SetTextureBlendMode(internals->composition, SDL_BLENDMODE_ADD);
|
||||
break;
|
||||
#if LV_GPU_SDL_CUSTOM_BLEND_MODE
|
||||
case LV_BLEND_MODE_SUBTRACTIVE: {
|
||||
SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE,
|
||||
SDL_BLENDOPERATION_SUBTRACT, SDL_BLENDFACTOR_ONE,
|
||||
SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT);
|
||||
SDL_SetTextureBlendMode(internals->composition, mode);
|
||||
break;
|
||||
}
|
||||
case LV_BLEND_MODE_MULTIPLY: {
|
||||
SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_COLOR,
|
||||
SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_ZERO,
|
||||
SDL_BLENDFACTOR_DST_ALPHA, SDL_BLENDOPERATION_ADD);
|
||||
SDL_SetTextureBlendMode(internals->composition, mode);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
LV_LOG_WARN("Doesn't support blend mode %d", blend_mode);
|
||||
SDL_SetTextureBlendMode(internals->composition, SDL_BLENDMODE_BLEND);
|
||||
/* Unsupported yet */
|
||||
break;
|
||||
}
|
||||
SDL_RenderCopy(ctx->renderer, internals->composition, &src_rect, &dst_rect);
|
||||
}
|
||||
|
||||
internals->mask = internals->composition = internals->target_backup = NULL;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
lv_point_t * tex_size = NULL;
|
||||
composite_key_t mask_key = mask_key_create(id);
|
||||
SDL_Texture * result = lv_draw_sdl_texture_cache_get_with_userdata(ctx, &mask_key, sizeof(composite_key_t), NULL,
|
||||
(void **) &tex_size);
|
||||
if(!result || tex_size->x < w || tex_size->y < h) {
|
||||
lv_coord_t size = next_pow_of_2(LV_MAX(w, h));
|
||||
int access = SDL_TEXTUREACCESS_STREAMING;
|
||||
if(id >= LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0) {
|
||||
access = SDL_TEXTUREACCESS_TARGET;
|
||||
}
|
||||
else if(id >= LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0) {
|
||||
access = SDL_TEXTUREACCESS_TARGET;
|
||||
}
|
||||
result = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, access, size, size);
|
||||
tex_size = lv_mem_alloc(sizeof(lv_point_t));
|
||||
tex_size->x = tex_size->y = size;
|
||||
lv_draw_sdl_texture_cache_put_advanced(ctx, &mask_key, sizeof(composite_key_t), result, tex_size, lv_mem_free, 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static composite_key_t mask_key_create(lv_draw_sdl_composite_texture_id_t type)
|
||||
{
|
||||
composite_key_t key;
|
||||
/* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_MASK;
|
||||
key.type = type;
|
||||
return key;
|
||||
}
|
||||
|
||||
static lv_coord_t next_pow_of_2(lv_coord_t num)
|
||||
{
|
||||
lv_coord_t n = 128;
|
||||
while(n < num && n < 16384) {
|
||||
n = n << 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords)
|
||||
{
|
||||
lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
SDL_assert(w > 0 && h > 0);
|
||||
SDL_Rect rect = {0, 0, w, h};
|
||||
uint8_t * pixels;
|
||||
int pitch;
|
||||
if(SDL_LockTexture(texture, &rect, (void **) &pixels, &pitch) != 0) return;
|
||||
|
||||
lv_opa_t * line_buf = lv_mem_buf_get(rect.w);
|
||||
for(lv_coord_t y = 0; y < rect.h; y++) {
|
||||
lv_memset_ff(line_buf, rect.w);
|
||||
lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) rect.w;
|
||||
lv_draw_mask_res_t res;
|
||||
res = lv_draw_mask_apply(line_buf, abs_x, abs_y, len);
|
||||
if(res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_memset_00(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else if(res == LV_DRAW_MASK_RES_FULL_COVER) {
|
||||
lv_memset_ff(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else {
|
||||
for(int x = 0; x < rect.w; x++) {
|
||||
const size_t idx = y * pitch + x * 4;
|
||||
pixels[idx] = line_buf[x];
|
||||
pixels[idx + 1] = pixels[idx + 2] = pixels[idx + 3] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
lv_mem_buf_release(line_buf);
|
||||
SDL_UnlockTexture(texture);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* @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_TRANSFORM0,
|
||||
} 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*/
|
||||
@@ -0,0 +1,467 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_img.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../lv_draw_img.h"
|
||||
#include "../lv_img_cache.h"
|
||||
#include "../lv_draw_mask.h"
|
||||
#include "../../misc/lv_lru.h"
|
||||
#include "../../misc/lv_gc.h"
|
||||
|
||||
#include "lv_draw_sdl_img.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_rect.h"
|
||||
#include "lv_draw_sdl_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
const SDL_Texture * texture;
|
||||
lv_coord_t w, h, radius;
|
||||
} lv_draw_img_rounded_key_t;
|
||||
|
||||
enum {
|
||||
ROUNDED_IMG_PART_LEFT = 0,
|
||||
ROUNDED_IMG_PART_HCENTER = 1,
|
||||
ROUNDED_IMG_PART_RIGHT = 2,
|
||||
ROUNDED_IMG_PART_TOP = 3,
|
||||
ROUNDED_IMG_PART_VCENTER = 4,
|
||||
ROUNDED_IMG_PART_BOTTOM = 5,
|
||||
};
|
||||
|
||||
enum {
|
||||
ROUNDED_IMG_CORNER_TOP_LEFT = 0,
|
||||
ROUNDED_IMG_CORNER_TOP_RIGHT = 1,
|
||||
ROUNDED_IMG_CORNER_BOTTOM_RIGHT = 2,
|
||||
ROUNDED_IMG_CORNER_BOTTOM_LEFT = 3,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static SDL_Texture * upload_img_texture(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
static SDL_Texture * upload_img_texture_fallback(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
static bool check_mask_simple_radius(const lv_area_t * coords, lv_coord_t * radius);
|
||||
|
||||
static void draw_img_simple(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header,
|
||||
const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip);
|
||||
|
||||
static void draw_img_rounded(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header,
|
||||
const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip,
|
||||
lv_coord_t radius);
|
||||
|
||||
static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture,
|
||||
const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius);
|
||||
|
||||
static lv_draw_img_rounded_key_t rounded_key_create(const SDL_Texture * texture, lv_coord_t w, lv_coord_t h,
|
||||
lv_coord_t radius);
|
||||
|
||||
static void calc_draw_part(SDL_Texture * texture, const lv_draw_sdl_img_header_t * header, const lv_area_t * coords,
|
||||
const lv_area_t * clip, SDL_Rect * clipped_src, SDL_Rect * clipped_dst);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
static void apply_recolor_opa(SDL_Texture * texture, const lv_draw_img_dsc_t * draw_dsc);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_res_t lv_draw_sdl_img_core(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords, const void * src)
|
||||
{
|
||||
const lv_area_t * clip = draw_ctx->clip_area;
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
|
||||
size_t key_size;
|
||||
lv_draw_sdl_cache_key_head_img_t * key = lv_draw_sdl_texture_img_key_create(src, draw_dsc->frame_id, &key_size);
|
||||
bool texture_found = false;
|
||||
lv_draw_sdl_img_header_t * header = NULL;
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get_with_userdata(ctx, key, key_size, &texture_found,
|
||||
(void **) &header);
|
||||
if(!texture_found) {
|
||||
lv_draw_sdl_img_load_texture(ctx, key, key_size, src, draw_dsc->frame_id, &texture, &header);
|
||||
}
|
||||
SDL_free(key);
|
||||
if(!texture) {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
lv_area_t zoomed_cords;
|
||||
_lv_img_buf_get_transformed_area(&zoomed_cords, lv_area_get_width(coords), lv_area_get_height(coords), 0,
|
||||
draw_dsc->zoom, &draw_dsc->pivot);
|
||||
lv_area_move(&zoomed_cords, coords->x1, coords->y1);
|
||||
|
||||
/* When in > 0, draw simple radius */
|
||||
lv_coord_t radius = 0;
|
||||
/* Coords will be translated so coords will start at (0,0) */
|
||||
lv_area_t t_coords = zoomed_cords, t_clip = *clip, apply_area;
|
||||
|
||||
bool has_composite = false;
|
||||
|
||||
if(!check_mask_simple_radius(&t_coords, &radius)) {
|
||||
has_composite = lv_draw_sdl_composite_begin(ctx, &zoomed_cords, clip, NULL, draw_dsc->blend_mode,
|
||||
&t_coords, &t_clip, &apply_area);
|
||||
}
|
||||
|
||||
lv_draw_sdl_transform_areas_offset(ctx, has_composite, &apply_area, &t_coords, &t_clip);
|
||||
|
||||
SDL_Rect clip_rect, coords_rect;
|
||||
lv_area_to_sdl_rect(&t_clip, &clip_rect);
|
||||
lv_area_to_sdl_rect(&t_coords, &coords_rect);
|
||||
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
|
||||
if(radius > 0) {
|
||||
draw_img_rounded(ctx, texture, header, draw_dsc, &t_coords, &t_clip, radius);
|
||||
}
|
||||
else {
|
||||
draw_img_simple(ctx, texture, header, draw_dsc, &t_coords, &t_clip);
|
||||
}
|
||||
|
||||
lv_draw_sdl_composite_end(ctx, &apply_area, draw_dsc->blend_mode);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static void calc_draw_part(SDL_Texture * texture, const lv_draw_sdl_img_header_t * header, const lv_area_t * coords,
|
||||
const lv_area_t * clip, SDL_Rect * clipped_src, SDL_Rect * clipped_dst)
|
||||
{
|
||||
double x = 0, y = 0, w, h;
|
||||
if(SDL_RectEmpty(&header->rect)) {
|
||||
Uint32 format = 0;
|
||||
int access = 0, tw, th;
|
||||
SDL_QueryTexture(texture, &format, &access, &tw, &th);
|
||||
w = tw;
|
||||
h = th;
|
||||
}
|
||||
else {
|
||||
x = header->rect.x;
|
||||
y = header->rect.y;
|
||||
w = header->rect.w;
|
||||
h = header->rect.h;
|
||||
}
|
||||
if(clip) {
|
||||
lv_area_t clipped_area;
|
||||
_lv_area_intersect(&clipped_area, coords, clip);
|
||||
lv_area_to_sdl_rect(&clipped_area, clipped_dst);
|
||||
}
|
||||
else {
|
||||
lv_area_to_sdl_rect(coords, clipped_dst);
|
||||
}
|
||||
lv_coord_t coords_w = lv_area_get_width(coords), coords_h = lv_area_get_height(coords);
|
||||
clipped_src->x = (int)(x + (clipped_dst->x - coords->x1) * w / coords_w);
|
||||
clipped_src->y = (int)(y + (clipped_dst->y - coords->y1) * h / coords_h);
|
||||
clipped_src->w = (int)(w - (coords_w - clipped_dst->w) * w / coords_w);
|
||||
clipped_src->h = (int)(h - (coords_h - clipped_dst->h) * h / coords_h);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
_lv_img_cache_entry_t * cdsc = _lv_img_cache_open(src, lv_color_white(), frame_id);
|
||||
lv_draw_sdl_cache_flag_t tex_flags = 0;
|
||||
SDL_Rect rect;
|
||||
SDL_memset(&rect, 0, sizeof(SDL_Rect));
|
||||
if(cdsc) {
|
||||
lv_img_decoder_dsc_t * dsc = &cdsc->dec_dsc;
|
||||
if(dsc->user_data && SDL_memcmp(dsc->user_data, LV_DRAW_SDL_DEC_DSC_TEXTURE_HEAD, 8) == 0) {
|
||||
lv_draw_sdl_dec_dsc_userdata_t * ptr = (lv_draw_sdl_dec_dsc_userdata_t *) dsc->user_data;
|
||||
*texture = ptr->texture;
|
||||
rect = ptr->rect;
|
||||
if(ptr->texture_managed) {
|
||||
tex_flags |= LV_DRAW_SDL_CACHE_FLAG_MANAGED;
|
||||
}
|
||||
ptr->texture_referenced = true;
|
||||
}
|
||||
else {
|
||||
*texture = upload_img_texture(ctx->renderer, dsc);
|
||||
}
|
||||
#if LV_IMG_CACHE_DEF_SIZE == 0
|
||||
lv_img_decoder_close(dsc);
|
||||
#endif
|
||||
}
|
||||
if(texture && cdsc) {
|
||||
*header = SDL_malloc(sizeof(lv_draw_sdl_img_header_t));
|
||||
SDL_memcpy(&(*header)->base, &cdsc->dec_dsc.header, sizeof(lv_img_header_t));
|
||||
(*header)->rect = rect;
|
||||
lv_draw_sdl_texture_cache_put_advanced(ctx, key, key_size, *texture, *header, SDL_free, tex_flags);
|
||||
}
|
||||
else {
|
||||
lv_draw_sdl_texture_cache_put(ctx, key, key_size, NULL);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static SDL_Texture * upload_img_texture(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc)
|
||||
{
|
||||
if(!dsc->img_data) {
|
||||
return upload_img_texture_fallback(renderer, dsc);
|
||||
}
|
||||
bool chroma_keyed = dsc->header.cf == (uint32_t) LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED;
|
||||
int h = (int) dsc->header.h;
|
||||
int w = (int) dsc->header.w;
|
||||
void * data = (void *) dsc->img_data;
|
||||
Uint32 rmask = 0x00FF0000;
|
||||
Uint32 gmask = 0x0000FF00;
|
||||
Uint32 bmask = 0x000000FF;
|
||||
Uint32 amask = 0xFF000000;
|
||||
if(chroma_keyed) {
|
||||
amask = 0x00;
|
||||
}
|
||||
SDL_Surface * surface = SDL_CreateRGBSurfaceFrom(data, w, h, LV_COLOR_DEPTH, w * LV_COLOR_DEPTH / 8,
|
||||
rmask, gmask, bmask, amask);
|
||||
SDL_SetColorKey(surface, chroma_keyed, lv_color_to32(LV_COLOR_CHROMA_KEY));
|
||||
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
return texture;
|
||||
}
|
||||
|
||||
static SDL_Texture * upload_img_texture_fallback(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc)
|
||||
{
|
||||
lv_coord_t h = (lv_coord_t) dsc->header.h;
|
||||
lv_coord_t w = (lv_coord_t) dsc->header.w;
|
||||
uint8_t * data = lv_mem_buf_get(w * h * sizeof(lv_color_t));
|
||||
for(lv_coord_t y = 0; y < h; y++) {
|
||||
lv_img_decoder_read_line(dsc, 0, y, w, &data[y * w * sizeof(lv_color_t)]);
|
||||
}
|
||||
Uint32 rmask = 0x00FF0000;
|
||||
Uint32 gmask = 0x0000FF00;
|
||||
Uint32 bmask = 0x000000FF;
|
||||
Uint32 amask = 0xFF000000;
|
||||
SDL_Surface * surface = SDL_CreateRGBSurfaceFrom(data, w, h, LV_COLOR_DEPTH, w * LV_COLOR_DEPTH / 8,
|
||||
rmask, gmask, bmask, amask);
|
||||
SDL_SetColorKey(surface, SDL_TRUE, lv_color_to32(LV_COLOR_CHROMA_KEY));
|
||||
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
lv_mem_buf_release(data);
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is only one radius mask
|
||||
* @param radius Set to radius value if the only mask is a radius mask
|
||||
* @return true if the only mask is a radius mask
|
||||
*/
|
||||
static bool check_mask_simple_radius(const lv_area_t * coords, lv_coord_t * radius)
|
||||
{
|
||||
if(lv_draw_mask_get_cnt() != 1) return false;
|
||||
for(uint8_t i = 0; i < _LV_MASK_MAX_NUM; i++) {
|
||||
_lv_draw_mask_common_dsc_t * param = LV_GC_ROOT(_lv_draw_mask_list[i]).param;
|
||||
if(param->type == LV_DRAW_MASK_TYPE_RADIUS) {
|
||||
lv_draw_mask_radius_param_t * rparam = (lv_draw_mask_radius_param_t *) param;
|
||||
if(rparam->cfg.outer) return false;
|
||||
if(!_lv_area_is_equal(&rparam->cfg.rect, coords)) return false;
|
||||
*radius = rparam->cfg.radius;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void draw_img_simple(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header,
|
||||
const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip)
|
||||
{
|
||||
apply_recolor_opa(texture, draw_dsc);
|
||||
SDL_Point pivot = {.x = draw_dsc->pivot.x, .y = draw_dsc->pivot.y};
|
||||
|
||||
/*Image needs to be rotated, so we have to use clip rect which is slower*/
|
||||
if(draw_dsc->angle != 0) {
|
||||
/* No radius, set clip here */
|
||||
SDL_Rect clip_rect;
|
||||
lv_area_to_sdl_rect(clip, &clip_rect);
|
||||
SDL_RenderSetClipRect(ctx->renderer, &clip_rect);
|
||||
}
|
||||
SDL_Rect src_rect, dst_rect;
|
||||
calc_draw_part(texture, header, coords, clip, &src_rect, &dst_rect);
|
||||
SDL_RenderCopyEx(ctx->renderer, texture, &src_rect, &dst_rect, draw_dsc->angle, &pivot, SDL_FLIP_NONE);
|
||||
if(draw_dsc->angle != 0) {
|
||||
SDL_RenderSetClipRect(ctx->renderer, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void draw_img_rounded(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header,
|
||||
const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip,
|
||||
lv_coord_t radius)
|
||||
{
|
||||
const int w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
lv_coord_t real_radius = LV_MIN3(radius, w, h);
|
||||
SDL_Texture * frag = img_rounded_frag_obtain(ctx, texture, header, w, h, real_radius);
|
||||
apply_recolor_opa(frag, draw_dsc);
|
||||
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, frag, real_radius, coords, clip, true);
|
||||
|
||||
apply_recolor_opa(texture, draw_dsc);
|
||||
|
||||
SDL_Rect src_rect, dst_rect;
|
||||
/* Draw 3 parts */
|
||||
lv_area_t clip_tmp, part;
|
||||
calc_draw_part(texture, header, coords, NULL, &src_rect, &dst_rect);
|
||||
for(int i = w > h ? ROUNDED_IMG_PART_LEFT : ROUNDED_IMG_PART_TOP, j = i + 3; i <= j; i++) {
|
||||
switch(i) {
|
||||
case ROUNDED_IMG_PART_LEFT:
|
||||
lv_area_set(&part, coords->x1, coords->y1 + radius, coords->x1 + radius - 1, coords->y2 - radius);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_HCENTER:
|
||||
lv_area_set(&part, coords->x1 + radius, coords->y1, coords->x2 - radius, coords->y2);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_RIGHT:
|
||||
lv_area_set(&part, coords->x2 - radius + 1, coords->y1 + radius, coords->x2, coords->y2 - radius);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_TOP:
|
||||
lv_area_set(&part, coords->x1 + radius, coords->y1, coords->x2 - radius, coords->y1 + radius - 1);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_VCENTER:
|
||||
lv_area_set(&part, coords->x1 + radius, coords->y2 - radius + 1, coords->x2 - radius, coords->y2);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_BOTTOM:
|
||||
lv_area_set(&part, coords->x1, coords->y1 + radius, coords->x2, coords->y2 - radius);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(!_lv_area_intersect(&clip_tmp, &part, clip)) continue;
|
||||
SDL_Rect clip_rect;
|
||||
lv_area_to_sdl_rect(&clip_tmp, &clip_rect);
|
||||
SDL_RenderSetClipRect(ctx->renderer, &clip_rect);
|
||||
SDL_RenderCopy(ctx->renderer, texture, &src_rect, &dst_rect);
|
||||
}
|
||||
SDL_RenderSetClipRect(ctx->renderer, NULL);
|
||||
}
|
||||
|
||||
static void apply_recolor_opa(SDL_Texture * texture, const lv_draw_img_dsc_t * draw_dsc)
|
||||
{
|
||||
if(draw_dsc->recolor_opa > LV_OPA_TRANSP) {
|
||||
/* Draw with mixed recolor */
|
||||
lv_color_t recolor = lv_color_mix(draw_dsc->recolor, lv_color_white(), draw_dsc->recolor_opa);
|
||||
SDL_SetTextureColorMod(texture, recolor.ch.red, recolor.ch.green, recolor.ch.blue);
|
||||
}
|
||||
else {
|
||||
/* Draw with no recolor */
|
||||
SDL_SetTextureColorMod(texture, 0xFF, 0xFF, 0xFF);
|
||||
}
|
||||
SDL_SetTextureAlphaMod(texture, draw_dsc->opa);
|
||||
}
|
||||
|
||||
static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture,
|
||||
const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius)
|
||||
{
|
||||
lv_draw_img_rounded_key_t key = rounded_key_create(texture, w, h, radius);
|
||||
SDL_Texture * mask_frag = lv_draw_sdl_rect_bg_frag_obtain(ctx, radius);
|
||||
SDL_Texture * img_frag = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
|
||||
if(img_frag == NULL) {
|
||||
const lv_coord_t full_frag_size = radius * 2 + 3;
|
||||
img_frag = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET,
|
||||
full_frag_size, full_frag_size);
|
||||
SDL_SetTextureBlendMode(img_frag, SDL_BLENDMODE_BLEND);
|
||||
SDL_Texture * old_target = SDL_GetRenderTarget(ctx->renderer);
|
||||
SDL_SetRenderTarget(ctx->renderer, img_frag);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, 0, 0, 0, 0);
|
||||
/* SDL_RenderClear is not working properly, so we overwrite the target with solid color */
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_RenderFillRect(ctx->renderer, NULL);
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
|
||||
|
||||
lv_area_t coords = {0, 0, w - 1, h - 1}, clip;
|
||||
lv_area_t frag_coords = {0, 0, full_frag_size - 1, full_frag_size - 1};
|
||||
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, mask_frag, radius, &frag_coords, NULL, false);
|
||||
|
||||
SDL_SetTextureAlphaMod(texture, 0xFF);
|
||||
SDL_SetTextureColorMod(texture, 0xFF, 0xFF, 0xFF);
|
||||
#if LV_GPU_SDL_CUSTOM_BLEND_MODE
|
||||
SDL_BlendMode blend_mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ZERO,
|
||||
SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_DST_ALPHA,
|
||||
SDL_BLENDFACTOR_ZERO, SDL_BLENDOPERATION_ADD);
|
||||
SDL_SetTextureBlendMode(texture, blend_mode);
|
||||
#else
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_MOD);
|
||||
#endif
|
||||
SDL_Rect srcrect, cliprect, dstrect = {0, 0, radius, radius};
|
||||
|
||||
cliprect.w = cliprect.h = radius;
|
||||
for(int i = 0; i <= ROUNDED_IMG_CORNER_BOTTOM_LEFT; i++) {
|
||||
switch(i) {
|
||||
case ROUNDED_IMG_CORNER_TOP_LEFT:
|
||||
cliprect.x = 0;
|
||||
cliprect.y = 0;
|
||||
lv_area_align(&frag_coords, &coords, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
break;
|
||||
case ROUNDED_IMG_CORNER_TOP_RIGHT:
|
||||
cliprect.x = full_frag_size - radius;
|
||||
cliprect.y = 0;
|
||||
lv_area_align(&frag_coords, &coords, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
break;
|
||||
case ROUNDED_IMG_CORNER_BOTTOM_RIGHT:
|
||||
cliprect.x = full_frag_size - radius;
|
||||
cliprect.y = full_frag_size - radius;
|
||||
lv_area_align(&frag_coords, &coords, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
|
||||
break;
|
||||
case ROUNDED_IMG_CORNER_BOTTOM_LEFT:
|
||||
cliprect.x = 0;
|
||||
cliprect.y = full_frag_size - radius;
|
||||
lv_area_align(&frag_coords, &coords, LV_ALIGN_BOTTOM_LEFT, 0, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
calc_draw_part(texture, header, &coords, NULL, &srcrect, &dstrect);
|
||||
SDL_RenderSetClipRect(ctx->renderer, &cliprect);
|
||||
SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect);
|
||||
}
|
||||
SDL_RenderSetClipRect(ctx->renderer, NULL);
|
||||
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
|
||||
SDL_SetRenderTarget(ctx->renderer, old_target);
|
||||
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), img_frag);
|
||||
}
|
||||
return img_frag;
|
||||
}
|
||||
|
||||
static lv_draw_img_rounded_key_t rounded_key_create(const SDL_Texture * texture, lv_coord_t w, lv_coord_t h,
|
||||
lv_coord_t radius)
|
||||
{
|
||||
lv_draw_img_rounded_key_t key;
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_IMG_ROUNDED_CORNERS;
|
||||
key.texture = texture;
|
||||
key.w = w;
|
||||
key.h = h;
|
||||
key.radius = radius;
|
||||
return key;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
@@ -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*/
|
||||
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_label.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "../lv_draw_label.h"
|
||||
#include "../../misc/lv_utils.h"
|
||||
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
const lv_font_t * font_p;
|
||||
uint32_t letter;
|
||||
} lv_font_glyph_key_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static lv_font_glyph_key_t font_key_glyph_create(const lv_font_t * font_p, uint32_t letter);
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
|
||||
uint32_t letter)
|
||||
{
|
||||
const lv_area_t * clip_area = draw_ctx->clip_area;
|
||||
const lv_font_t * font_p = dsc->font;
|
||||
lv_opa_t opa = dsc->opa;
|
||||
lv_color_t color = dsc->color;
|
||||
if(opa < LV_OPA_MIN) return;
|
||||
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
|
||||
|
||||
if(font_p == NULL) {
|
||||
LV_LOG_WARN("lv_draw_letter: font is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_font_glyph_dsc_t g;
|
||||
bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0');
|
||||
if(g_ret == false) {
|
||||
/*Add warning if the dsc is not found
|
||||
*but do not print warning for non printable ASCII chars (e.g. '\n')*/
|
||||
if(letter >= 0x20 &&
|
||||
letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/
|
||||
letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/
|
||||
LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%X", letter);
|
||||
|
||||
/* draw placeholder */
|
||||
lv_area_t glyph_coords;
|
||||
lv_draw_rect_dsc_t glyph_dsc;
|
||||
lv_coord_t begin_x = pos_p->x + g.ofs_x;
|
||||
lv_coord_t begin_y = pos_p->y + g.ofs_y;
|
||||
lv_area_set(&glyph_coords, begin_x, begin_y, begin_x + g.box_w, begin_y + g.box_h);
|
||||
lv_draw_rect_dsc_init(&glyph_dsc);
|
||||
glyph_dsc.bg_opa = LV_OPA_MIN;
|
||||
glyph_dsc.outline_opa = LV_OPA_MIN;
|
||||
glyph_dsc.shadow_opa = LV_OPA_MIN;
|
||||
glyph_dsc.bg_img_opa = LV_OPA_MIN;
|
||||
glyph_dsc.border_color = dsc->color;
|
||||
glyph_dsc.border_width = 1;
|
||||
draw_ctx->draw_rect(draw_ctx, &glyph_dsc, &glyph_coords);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*Don't draw anything if the character is empty. E.g. space*/
|
||||
if((g.box_h == 0) || (g.box_w == 0)) return;
|
||||
|
||||
int32_t pos_x = pos_p->x + g.ofs_x;
|
||||
int32_t pos_y = pos_p->y + (font_p->line_height - font_p->base_line) - g.box_h - g.ofs_y;
|
||||
|
||||
const lv_area_t letter_area = {pos_x, pos_y, pos_x + g.box_w - 1, pos_y + g.box_h - 1};
|
||||
lv_area_t draw_area;
|
||||
|
||||
/*If the letter is completely out of mask don't draw it*/
|
||||
if(!_lv_area_intersect(&draw_area, &letter_area, clip_area)) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
SDL_Renderer * renderer = ctx->renderer;
|
||||
|
||||
lv_font_glyph_key_t glyph_key = font_key_glyph_create(font_p, letter);
|
||||
bool glyph_found = false;
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &glyph_key, sizeof(glyph_key), &glyph_found);
|
||||
if(!glyph_found) {
|
||||
if(g.resolved_font) {
|
||||
font_p = g.resolved_font;
|
||||
}
|
||||
const uint8_t * bmp = lv_font_get_glyph_bitmap(font_p, letter);
|
||||
uint8_t * buf = lv_mem_alloc(g.box_w * g.box_h);
|
||||
lv_sdl_to_8bpp(buf, bmp, g.box_w, g.box_h, g.box_w, g.bpp);
|
||||
SDL_Surface * mask = lv_sdl_create_opa_surface(buf, g.box_w, g.box_h, g.box_w);
|
||||
texture = SDL_CreateTextureFromSurface(renderer, mask);
|
||||
SDL_FreeSurface(mask);
|
||||
lv_mem_free(buf);
|
||||
lv_draw_sdl_texture_cache_put(ctx, &glyph_key, sizeof(glyph_key), texture);
|
||||
}
|
||||
if(!texture) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_area_t t_letter = letter_area, t_clip = *clip_area, apply_area;
|
||||
bool has_composite = lv_draw_sdl_composite_begin(ctx, &letter_area, clip_area, NULL, dsc->blend_mode, &t_letter,
|
||||
&t_clip, &apply_area);
|
||||
|
||||
lv_draw_sdl_transform_areas_offset(ctx, has_composite, &apply_area, &t_letter, &t_clip);
|
||||
|
||||
/*If the letter is completely out of mask don't draw it*/
|
||||
if(!_lv_area_intersect(&draw_area, &t_letter, &t_clip)) {
|
||||
return;
|
||||
}
|
||||
SDL_Rect srcrect, dstrect;
|
||||
lv_area_to_sdl_rect(&draw_area, &dstrect);
|
||||
srcrect.x = draw_area.x1 - t_letter.x1;
|
||||
srcrect.y = draw_area.y1 - t_letter.y1;
|
||||
srcrect.w = dstrect.w;
|
||||
srcrect.h = dstrect.h;
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetTextureAlphaMod(texture, opa);
|
||||
SDL_SetTextureColorMod(texture, color.ch.red, color.ch.green, color.ch.blue);
|
||||
SDL_RenderCopy(renderer, texture, &srcrect, &dstrect);
|
||||
|
||||
lv_draw_sdl_composite_end(ctx, &apply_area, dsc->blend_mode);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_font_glyph_key_t font_key_glyph_create(const lv_font_t * font_p, uint32_t letter)
|
||||
{
|
||||
lv_font_glyph_key_t key;
|
||||
/* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_FONT_GLYPH;
|
||||
key.font_p = font_p;
|
||||
key.letter = letter;
|
||||
return key;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user