Compare commits

..

2 Commits

Author SHA1 Message Date
ym-terada
4d96c27ce3 fix(event): fix LV_EVENT_PREPROCESS flag was not processed correctly on VisualStudio (#6169) 2024-05-06 14:48:54 +02:00
Gabor Kiss-Vamosi
36a8052510 chore: kick CI to rebuild the docs 2024-04-23 15:56:46 +02:00
47 changed files with 2632 additions and 1927 deletions

View File

@@ -1,10 +1,8 @@
### Description of the feature or fix
A clear and concise description of what the bug or new feature is.
- Update the [Documentation](https://github.com/lvgl/lvgl/tree/master/docs) if needed.
- Add [Examples](https://github.com/lvgl/lvgl/tree/master/examples) if relevant.
- Add [Tests](https://github.com/lvgl/lvgl/blob/master/tests/README.md) if applicable.
- If you added new options to `lv_conf_template.h` run [lv_conf_internal_gen.py](https://github.com/lvgl/lvgl/blob/master/scripts/lv_conf_internal_gen.py) and update [Kconfig](https://github.com/lvgl/lvgl/blob/master/Kconfig).
- Run `scripts/code-format.py` (`astyle v3.4.12` needs to installed by running `cd scripts; ./install_astyle.sh`) and follow the [Code Conventions](https://docs.lvgl.io/master/CODING_STYLE.html).
- Mark the Pull request as [Draft](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request) while you are working on the first version, and mark is as _Ready_ when it's ready for review.
- When changes were requested, [re-request review](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/requesting-a-pull-request-review) to notify the maintainers.
- Help us to review this Pull Request! Anyone can [approve or request changes](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/approving-a-pull-request-with-required-reviews).
### Checkpoints
- [ ] Follow the [styling guide](https://github.com/lvgl/lvgl/blob/master/docs/CODING_STYLE.md)
- [ ] Run `code-format.py` from the `scripts` folder. [astyle](http://astyle.sourceforge.net/install.html) needs to be installed.
- [ ] Update the documentation

View File

@@ -16,8 +16,9 @@ jobs:
- name: Checkout astyle
uses: actions/checkout@v4
with:
repository: lvgl/astyle
repository: szepeviktor/astyle
path: astyle
ref: v3.4.12
- name: Install astyle
run: |
cd astyle/build/gcc/

View File

@@ -1,4 +1,4 @@
# Kconfig file for LVGL v8.4
# Kconfig file for LVGL v8.0
menu "LVGL configuration"

File diff suppressed because it is too large Load Diff

View File

@@ -67,7 +67,7 @@ The keyboard has a **default event handler** callback called `lv_keyboard_def_ev
Learn more about [Events](/overview/event).
## Keys
- `LV_KEY_DOWN/UP/LEFT/RIGHT` To navigate among the buttons and select one.
- `LV_KEY_RIGHT/UP/LEFT/RIGHT` To navigate among the buttons and select one.
- `LV_KEY_ENTER` To press/release the selected button.
Learn more about [Keys](/overview/indev).

View File

@@ -36,11 +36,7 @@
<repository type="git">https://github.com/lvgl/lvgl.git</repository>
<releases>
<release date="2024-03-19" version="8.4.0" url="https://github.com/lvgl/lvgl/raw/v8.4.0/env_support/cmsis-pack/LVGL.lvgl.8.4.0.pack">
- LVGL 8.4.0
- Some minor fixes
</release>
<release date="2023-12-05" version="8.3.11" url="https://github.com/lvgl/lvgl/raw/v8.3.11/env_support/cmsis-pack/LVGL.lvgl.8.3.11.pack">
<release date="2023-12-05" version="8.3.11" url="https://raw.githubusercontent.com/lvgl/lvgl/master/env_support/cmsis-pack/LVGL.lvgl.8.3.11.pack">
- LVGL 8.3.11
- Add LittleFS Library to LVGL8
- Backport Tiny TTF to LVGL8
@@ -314,7 +310,7 @@
-->
<components>
<bundle Cbundle="LVGL" Cclass="LVGL" Cversion="8.4.0">
<bundle Cbundle="LVGL" Cclass="LVGL" Cversion="8.3.11">
<description>LVGL (Light and Versatile Graphics Library) is a free and open-source graphics library providing everything you need to create an embedded GUI with easy-to-use graphical elements, beautiful visual effects and a low memory footprint.</description>
<doc></doc>
<component Cgroup="lvgl" Csub="Essential" >
@@ -447,7 +443,7 @@
<file category="sourceC" name="src/widgets/lv_textarea.c" />
<!-- general -->
<file category="preIncludeGlobal" name="lv_conf_cmsis.h" attr="config" version="1.0.5" />
<file category="preIncludeGlobal" name="lv_conf_cmsis.h" attr="config" version="1.0.4" />
<file category="sourceC" name="lv_cmsis_pack.c" attr="config" version="1.0.0" />
<file category="header" name="lvgl.h" />
<file category="doc" name="README.md"/>

View File

@@ -2,8 +2,8 @@
<index schemaVersion="1.0.0" xs:noNamespaceSchemaLocation="PackIndex.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
<vendor>LVGL</vendor>
<url>https://raw.githubusercontent.com/lvgl/lvgl/master/env_support/cmsis-pack/</url>
<timestamp>2024-3-19</timestamp>
<timestamp>2023-12-09</timestamp>
<pindex>
<pdsc url="https://raw.githubusercontent.com/lvgl/lvgl/release/v8.3/env_support/cmsis-pack/" vendor="LVGL" name="lvgl" version="8.4.0"/>
<pdsc url="https://raw.githubusercontent.com/lvgl/lvgl/release/v8.3/env_support/cmsis-pack/" vendor="LVGL" name="lvgl" version="8.3.11"/>
</pindex>
</index>

View File

@@ -35,9 +35,7 @@ remove the misleading guide above this code segment.
#define LV_CONF_H
#include <stdint.h>
#if defined(_RTE_)
#include "RTE_Components.h"
#endif
#include "RTE_Components.h"
...
```

View File

@@ -1,6 +1,6 @@
/**
* @file lv_conf.h
* Configuration file for v8.4.0
* Configuration file for v8.3.11
*/
/* clang-format off */
@@ -10,10 +10,7 @@
#define LV_CONF_H
#include <stdint.h>
#if defined(_RTE_)
#include "RTE_Components.h"
#endif
#include "RTE_Components.h"
/*====================
COLOR SETTINGS

View File

@@ -1,6 +1,6 @@
{
"name": "lvgl",
"version": "8.4.0",
"version": "8.3.11",
"keywords": "graphics, gui, embedded, tft, lvgl",
"description": "Graphics library to create embedded GUI with easy-to-use graphical elements, beautiful visual effects and low memory footprint. It offers anti-aliasing, opacity, and animations using only one frame buffer.",
"repository": {

View File

@@ -1,5 +1,5 @@
name=lvgl
version=8.4.0
version=8.3.11
author=kisvegabor
maintainer=kisvegabor,embeddedt,pete-pjb
sentence=Full-featured Graphics Library for Embedded Systems

View File

@@ -1,6 +1,6 @@
/**
* @file lv_conf.h
* Configuration file for v8.4.0
* Configuration file for v8.3.11
*/
/*
@@ -176,9 +176,6 @@
* GPU
*-----------*/
/*Use TSi's (aka Think Silicon) acceleration library NemaGFX */
#define LV_USE_NEMA_GFX 0
/*Use Arm's 2D acceleration library Arm-2D */
#define LV_USE_GPU_ARM2D 0

6
lvgl.h
View File

@@ -14,9 +14,9 @@ extern "C" {
* CURRENT VERSION OF LVGL
***************************/
#define LVGL_VERSION_MAJOR 8
#define LVGL_VERSION_MINOR 4
#define LVGL_VERSION_PATCH 1
#define LVGL_VERSION_INFO "dev"
#define LVGL_VERSION_MINOR 3
#define LVGL_VERSION_PATCH 11
#define LVGL_VERSION_INFO ""
/*********************
* INCLUDES

View File

@@ -5,6 +5,6 @@ libdir=${prefix}/lib
Name: lvgl
Description: Light and Versatile Graphics Library
URL: https://lvgl.io/
Version: 8.4.0
Version: 8.3.11
Cflags: -I${includedir}
Libs: -L${libdir} -llvgl

View File

@@ -1,9 +0,0 @@
#!/bin/sh
rm -rf astyle
git clone https://github.com/lvgl/astyle.git
cd astyle/build/gcc
make -j
make install
cd ../../..
rm -rf astyle

View File

@@ -230,12 +230,14 @@ void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t
/*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) {
if(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);
d->prev_scr = d->act_scr;
if(d->del_prev) {
lv_obj_del(act_scr);
}
act_scr = d->scr_to_load;
scr_load_internal(d->scr_to_load);

View File

@@ -71,8 +71,6 @@ lv_group_t * lv_group_create(void)
void lv_group_del(lv_group_t * group)
{
LV_ASSERT_NULL(group);
/*Defocus the currently focused object*/
if(group->obj_focus != NULL) {
lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
@@ -218,8 +216,6 @@ void lv_group_remove_obj(lv_obj_t * obj)
void lv_group_remove_all_objs(lv_group_t * group)
{
LV_ASSERT_NULL(group);
/*Defocus the currently focused object*/
if(group->obj_focus != NULL) {
lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
@@ -271,8 +267,6 @@ void lv_group_focus_obj(lv_obj_t * obj)
void lv_group_focus_next(lv_group_t * group)
{
LV_ASSERT_NULL(group);
bool focus_changed = focus_next_core(group, _lv_ll_get_head, _lv_ll_get_next);
if(group->edge_cb) {
if(!focus_changed)
@@ -282,8 +276,6 @@ void lv_group_focus_next(lv_group_t * group)
void lv_group_focus_prev(lv_group_t * group)
{
LV_ASSERT_NULL(group);
bool focus_changed = focus_next_core(group, _lv_ll_get_tail, _lv_ll_get_prev);
if(group->edge_cb) {
if(!focus_changed)
@@ -293,8 +285,6 @@ void lv_group_focus_prev(lv_group_t * group)
void lv_group_focus_freeze(lv_group_t * group, bool en)
{
LV_ASSERT_NULL(group);
if(en == false) group->frozen = 0;
else group->frozen = 1;
}
@@ -311,15 +301,11 @@ lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c)
void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb)
{
LV_ASSERT_NULL(group);
group->focus_cb = focus_cb;
}
void lv_group_set_edge_cb(lv_group_t * group, lv_group_edge_cb_t edge_cb)
{
LV_ASSERT_NULL(group);
group->edge_cb = edge_cb;
}
@@ -343,15 +329,11 @@ void lv_group_set_editing(lv_group_t * group, bool edit)
void lv_group_set_refocus_policy(lv_group_t * group, lv_group_refocus_policy_t policy)
{
LV_ASSERT_NULL(group);
group->refocus_policy = policy & 0x01;
}
void lv_group_set_wrap(lv_group_t * group, bool en)
{
LV_ASSERT_NULL(group);
group->wrap = en ? 1 : 0;
}
@@ -389,8 +371,6 @@ bool lv_group_get_wrap(lv_group_t * group)
uint32_t lv_group_get_obj_count(lv_group_t * group)
{
LV_ASSERT_NULL(group);
return _lv_ll_get_len(&group->obj_ll);
}
/**********************
@@ -399,8 +379,6 @@ uint32_t lv_group_get_obj_count(lv_group_t * group)
static void lv_group_refocus(lv_group_t * g)
{
LV_ASSERT_NULL(g);
/*Refocus must temporarily allow wrapping to work correctly*/
uint8_t temp_wrap = g->wrap;
g->wrap = 1;
@@ -416,8 +394,6 @@ static void lv_group_refocus(lv_group_t * g)
static bool focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *),
void * (*move)(const lv_ll_t *, const void *))
{
LV_ASSERT_NULL(group);
bool focus_changed = false;
if(group->frozen) return focus_changed;

View File

@@ -42,10 +42,6 @@
#include "../draw/nxp/pxp/lv_gpu_nxp_pxp.h"
#endif
#if LV_USE_NEMA_GFX
#include "../draw/nema_gfx/lv_draw_nema_gfx.h"
#endif
/*********************
* DEFINES
*********************/
@@ -141,11 +137,6 @@ void lv_init(void)
PXP_COND_STOP(!lv_gpu_nxp_pxp_init(), "PXP init failed.");
#endif
#if LV_USE_NEMA_GFX
/*Initialize NEMA GPU*/
lv_draw_nema_gfx_init();
#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));

View File

@@ -75,13 +75,8 @@ void _lv_obj_style_init(void)
void lv_obj_add_style(lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector)
{
LV_ASSERT(obj->style_cnt < 63);
trans_del(obj, selector, LV_STYLE_PROP_ANY, NULL);
/*Try removing the style first to be sure it won't be added twice*/
lv_obj_remove_style(obj, style, selector);
uint32_t i;
/*Go after the transition and local styles*/
for(i = 0; i < obj->style_cnt; i++) {
@@ -94,9 +89,7 @@ void lv_obj_add_style(lv_obj_t * obj, lv_style_t * style, lv_style_selector_t se
/*Allocate space for the new style and shift the rest of the style to the end*/
obj->style_cnt++;
LV_ASSERT(obj->style_cnt != 0);
obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t));
LV_ASSERT_MALLOC(obj->styles);
uint32_t j;
for(j = obj->style_cnt - 1; j > i ; j--) {
@@ -555,7 +548,6 @@ static lv_style_t * get_local_style(lv_obj_t * obj, lv_style_selector_t selector
}
obj->style_cnt++;
LV_ASSERT(obj->style_cnt != 0);
obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t));
LV_ASSERT_MALLOC(obj->styles);
@@ -592,9 +584,7 @@ static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, lv_style_selector_t se
if(i != obj->style_cnt) return &obj->styles[i];
obj->style_cnt++;
LV_ASSERT(obj->style_cnt != 0);
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--) {
obj->styles[i] = obj->styles[i - 1];

View File

@@ -89,8 +89,6 @@
#define arm_2d_tile_copy arm_2d_rgb16_tile_copy
#define arm_2d_alpha_blending arm_2d_rgb565_alpha_blending
#define arm_2d_tile_copy_with_src_mask arm_2d_rgb565_tile_copy_with_src_mask
#define __arm_2d_impl_tile_copy_with_src_mask_and_opacity \
__arm_2d_impl_rgb565_tile_copy_with_src_mask_and_opacity
#define arm_2d_color_t arm_2d_color_rgb565_t
/* arm-2d direct mode apis */
@@ -130,8 +128,6 @@
#define arm_2d_tile_copy arm_2d_rgb32_tile_copy
#define arm_2d_alpha_blending arm_2d_cccn888_alpha_blending
#define arm_2d_tile_copy_with_src_mask arm_2d_cccn888_tile_copy_with_src_mask
#define __arm_2d_impl_tile_copy_with_src_mask_and_opacity \
__arm_2d_impl_cccn888_tile_copy_with_src_mask_and_opacity
#define arm_2d_color_t arm_2d_color_cccn888_t
/* arm-2d direct mode apis */
@@ -419,6 +415,19 @@
* STATIC PROTOTYPES
**********************/
#if __ARM_2D_HAS_HW_ACC__
static bool /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_arm2d_fill_colour(const arm_2d_tile_t * target_tile,
const arm_2d_region_t * region,
lv_color_t color,
lv_opa_t opa,
const arm_2d_tile_t * mask_tile);
static bool /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_arm2d_tile_copy(const arm_2d_tile_t * target_tile,
const arm_2d_region_t * region,
arm_2d_tile_t * source_tile,
lv_opa_t opa,
arm_2d_tile_t * mask_tile);
#else
static void convert_cb(const lv_area_t * dest_area,
const void * src_buf,
@@ -446,7 +455,7 @@ static bool /* LV_ATTRIBUTE_FAST_MEM */ arm_2d_copy_normal(lv_color_t * dest_buf
lv_opa_t opa,
const lv_opa_t * mask,
lv_coord_t mask_stride);
#endif
static void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx,
const lv_draw_sw_blend_dsc_t * dsc);
@@ -480,7 +489,9 @@ void lv_draw_arm2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
arm2d_draw_ctx->blend = lv_draw_arm2d_blend;
arm2d_draw_ctx->base_draw.wait_for_finish = lv_gpu_arm2d_wait_cb;
#if !__ARM_2D_HAS_HW_ACC__
arm2d_draw_ctx->base_draw.draw_img_decoded = lv_draw_arm2d_img_decoded;
#endif
}
@@ -492,6 +503,180 @@ void lv_draw_arm2d_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
extern void test_flush(lv_color_t * color_p);
#if __ARM_2D_HAS_HW_ACC__
static void LV_ATTRIBUTE_FAST_MEM lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx,
const lv_draw_sw_blend_dsc_t * dsc)
{
const lv_opa_t * mask;
if(dsc->mask_buf == NULL) mask = NULL;
if(dsc->mask_buf && dsc->mask_res == LV_DRAW_MASK_RES_TRANSP) return;
else if(dsc->mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask = NULL;
else mask = dsc->mask_buf;
lv_area_t blend_area;
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) {
return;
}
bool is_accelerated = false;
if(dsc->blend_mode == LV_BLEND_MODE_NORMAL
&& lv_area_get_size(&blend_area) > 100) {
__PREPARE_TARGET_TILE__(blend_area);
__PREPARE_SOURCE_TILE__(dsc, blend_area);
__PREPARE_MASK_TILE__(dsc, blend_area, mask, false);
if(src_buf) {
is_accelerated = lv_draw_arm2d_tile_copy(
&target_tile,
&target_region,
&source_tile,
dsc->opa,
(NULL == mask) ? NULL : &mask_tile);
}
else {
is_accelerated = lv_draw_arm2d_fill_colour(
&target_tile,
&target_region,
dsc->color,
dsc->opa,
(NULL == mask) ? NULL : &mask_tile);
}
}
if(!is_accelerated) {
lv_draw_sw_blend_basic(draw_ctx, dsc);
}
}
static bool LV_ATTRIBUTE_FAST_MEM lv_draw_arm2d_fill_colour(const arm_2d_tile_t * target_tile,
const arm_2d_region_t * region,
lv_color_t color,
lv_opa_t opa,
const arm_2d_tile_t * mask_tile)
{
arm_fsm_rt_t result = (arm_fsm_rt_t)ARM_2D_ERR_NONE;
if(NULL == mask_tile) {
if(opa >= LV_OPA_MAX) {
result = arm_2d_fill_colour(target_tile, region, color.full);
}
else {
#if LV_COLOR_SCREEN_TRANSP
return false;
#else
result = arm_2d_fill_colour_with_alpha(
target_tile,
region,
(arm_2d_color_t) {
color.full
},
opa);
#endif
}
}
else {
if(opa >= LV_OPA_MAX) {
result = arm_2d_fill_colour_with_mask(
target_tile,
region,
mask_tile,
(arm_2d_color_t) {
color.full
});
}
else {
#if LV_COLOR_SCREEN_TRANSP
return false;
#else
result = arm_2d_fill_colour_with_mask_and_opacity(
target_tile,
region,
mask_tile,
(arm_2d_color_t) {
color.full
},
opa);
#endif
}
}
if(result < 0) {
/* error detected */
return false;
}
return true;
}
static bool LV_ATTRIBUTE_FAST_MEM lv_draw_arm2d_tile_copy(const arm_2d_tile_t * target_tile,
const arm_2d_region_t * region,
arm_2d_tile_t * source_tile,
lv_opa_t opa,
arm_2d_tile_t * mask_tile)
{
arm_fsm_rt_t result = (arm_fsm_rt_t)ARM_2D_ERR_NONE;
if(NULL == mask_tile) {
if(opa >= LV_OPA_MAX) {
result = arm_2d_tile_copy(source_tile,
target_tile,
region,
ARM_2D_CP_MODE_COPY);
}
#if LV_COLOR_SCREEN_TRANSP
else {
return false; /* not supported */
}
#else
else {
result = arm_2d_alpha_blending(source_tile,
target_tile,
region,
opa);
}
#endif
}
else {
#if LV_COLOR_SCREEN_TRANSP
return false; /* not support */
#else
if(opa >= LV_OPA_MAX) {
result = arm_2d_tile_copy_with_src_mask(source_tile,
mask_tile,
target_tile,
region,
ARM_2D_CP_MODE_COPY);
}
else {
return false;
}
#endif
}
if(result < 0) {
/* error detected */
return false;
}
return true;
}
static void lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx)
{
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
arm_2d_op_wait_async(NULL);
if(disp->driver && disp->driver->wait_cb) {
disp->driver->wait_cb(disp->driver);
}
lv_draw_sw_wait_for_finish(draw_ctx);
}
#else
static void LV_ATTRIBUTE_FAST_MEM lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx,
const lv_draw_sw_blend_dsc_t * dsc)
@@ -686,15 +871,20 @@ static bool LV_ATTRIBUTE_FAST_MEM arm_2d_copy_normal(lv_color_t * dest_buf,
}
/*Handle opa and mask values too*/
else {
__arm_2d_impl_tile_copy_with_src_mask_and_opacity((color_int *)src_buf,
src_stride,
(uint8_t *)mask,
mask_stride,
&copy_size,
(color_int *)dest_buf,
dest_stride,
&copy_size,
opa);
__arm_2d_impl_gray8_colour_filling_with_opacity((uint8_t *)mask,
mask_stride,
&copy_size,
0x00,
255 - opa);
__arm_2d_impl_src_msk_copy((color_int *)src_buf,
src_stride,
(uint8_t *)mask,
mask_stride,
&copy_size,
(color_int *)dest_buf,
dest_stride,
&copy_size);
}
}
@@ -806,8 +996,8 @@ static void LV_ATTRIBUTE_FAST_MEM lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_
if(cf == LV_IMG_CF_ALPHA_8BIT) {
/* original code:
lv_color_fill(rgb_buf, draw_dsc->recolor, buf_size);
*/
lv_color_fill(rgb_buf, draw_dsc->recolor, buf_size);
*/
arm_2d_size_t copy_size = {
.iWidth = buf_w,
.iHeight = buf_h,
@@ -827,141 +1017,187 @@ static void LV_ATTRIBUTE_FAST_MEM lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_
if(LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf) {
/* copy with colour keying */
/* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
/* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
lv_color_t chrome_key = LV_COLOR_CHROMA_KEY;
/* calculate new chrome-key colour */
if(draw_dsc->recolor_opa > LV_OPA_MIN) {
__ARM_2D_PIXEL_BLENDING_OPA(
(color_int *) & (draw_dsc->recolor.full),
(color_int *) & (chrome_key.full),
draw_dsc->recolor_opa
);
}
lv_color_t chrome_key = LV_COLOR_CHROMA_KEY;
/* calculate new chrome-key colour */
if(draw_dsc->recolor_opa > LV_OPA_MIN) {
__ARM_2D_PIXEL_BLENDING_OPA(
(color_int *) & (draw_dsc->recolor.full),
(color_int *) & (chrome_key.full),
draw_dsc->recolor_opa
);
}
__PREPARE_LL_ACCELERATION__();
__PREPARE_LL_ACCELERATION__();
if(blend_dsc.opa >= LV_OPA_MAX) {
__arm_2d_impl_cl_key_copy(
(color_int *)src_buf_tmp,
src_stride,
(color_int *)dest_buf,
dest_stride,
&copy_size,
(color_int)chrome_key.full);
}
else {
__arm_2d_impl_alpha_blending_colour_keying(
if(blend_dsc.opa >= LV_OPA_MAX) {
__arm_2d_impl_cl_key_copy(
(color_int *)src_buf_tmp,
src_stride,
(color_int *)dest_buf,
dest_stride,
&copy_size,
blend_dsc.opa,
(color_int)chrome_key.full);
}
is_accelerated = true;
)
/* *INDENT-ON* */
}
else {
__arm_2d_impl_alpha_blending_colour_keying(
(color_int *)src_buf_tmp,
src_stride,
(color_int *)dest_buf,
dest_stride,
&copy_size,
blend_dsc.opa,
(color_int)chrome_key.full);
}
is_accelerated = true;
)
/* *INDENT-ON* */
}
else if((LV_COLOR_DEPTH == 32)
&& !mask_any
&& (LV_IMG_CF_TRUE_COLOR_ALPHA == cf)) {
/* accelerate copy-with-source-masks-and-opacity */
/* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
__PREPARE_LL_ACCELERATION__();
/* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
__PREPARE_LL_ACCELERATION__();
uint8_t * mask_temp_buf = NULL;
if(blend_dsc.opa < LV_OPA_MAX) {
__arm_2d_impl_ccca8888_tile_copy_to_cccn888_with_opacity(
(uint32_t *)src_buf_tmp,
src_stride,
(uint32_t *)dest_buf,
dest_stride,
&copy_size,
blend_dsc.opa);
}
else {
__arm_2d_impl_ccca8888_to_cccn888(
(uint32_t *)src_buf_tmp,
src_stride,
(uint32_t *)dest_buf,
dest_stride,
&copy_size);
}
uint8_t * mask_temp_buf = NULL;
if(blend_dsc.opa < LV_OPA_MAX) {
mask_temp_buf = lv_mem_buf_get(copy_size.iHeight * copy_size.iWidth);
if(NULL == mask_temp_buf) {
LV_LOG_WARN(
"Failed to allocate memory for alpha mask,"
" use normal route instead.");
break;
}
lv_memset_00(mask_temp_buf, copy_size.iHeight * copy_size.iWidth);
is_accelerated = true;
)
/* *INDENT-ON* */
__arm_2d_impl_gray8_colour_filling_channel_mask_opacity(
mask_temp_buf,
src_stride,
(uint32_t *)
((uintptr_t)src_buf_tmp + LV_IMG_PX_SIZE_ALPHA_BYTE - 1),
src_stride,
&copy_size,
0xFF,
blend_dsc.opa);
__arm_2d_impl_src_msk_copy(
(color_int *)src_buf_tmp,
src_stride,
mask_temp_buf,
src_stride,
&copy_size,
(color_int *)dest_buf,
dest_stride,
&copy_size);
lv_mem_buf_release(mask_temp_buf);
}
else {
__arm_2d_impl_src_chn_msk_copy(
(color_int *)src_buf_tmp,
src_stride,
(uint32_t *)
((uintptr_t)src_buf_tmp + LV_IMG_PX_SIZE_ALPHA_BYTE - 1),
src_stride,
&copy_size,
(color_int *)dest_buf,
dest_stride,
&copy_size);
}
is_accelerated = true;
)
/* *INDENT-ON* */
}
else if(!mask_any
&& (LV_IMG_CF_RGB565A8 == cf)) {
/* accelerate copy-with-source-masks-and-opacity */
uint8_t * mask_after_rgb = src_buf + sizeof(lv_color_t) * src_w * src_h;
/* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
__PREPARE_LL_ACCELERATION__();
/* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
__PREPARE_LL_ACCELERATION__();
uint8_t * mask_temp_buf = NULL;
if(blend_dsc.opa < LV_OPA_MAX) {
__arm_2d_impl_rgb565_tile_copy_with_src_mask_and_opacity(
(uint16_t *)src_buf_tmp,
src_stride,
(uint8_t *)mask_after_rgb,
src_stride,
&copy_size,
(uint16_t *)dest_buf,
dest_stride,
&copy_size,
blend_dsc.opa);
}
else {
__arm_2d_impl_src_msk_copy(
(color_int *)src_buf_tmp,
src_stride,
mask_after_rgb,
src_stride,
&copy_size,
(color_int *)dest_buf,
dest_stride,
&copy_size);
}
uint8_t * mask_temp_buf = NULL;
if(blend_dsc.opa < LV_OPA_MAX) {
mask_temp_buf = lv_mem_buf_get(copy_size.iHeight * copy_size.iWidth);
if(NULL == mask_temp_buf) {
LV_LOG_WARN(
"Failed to allocate memory for alpha mask,"
" use normal route instead.");
break;
}
lv_memset_00(mask_temp_buf, copy_size.iHeight * copy_size.iWidth);
is_accelerated = true;
)
/* *INDENT-ON* */
__arm_2d_impl_gray8_colour_filling_mask_opacity(
mask_temp_buf,
src_stride,
mask_after_rgb,
src_stride,
&copy_size,
0xFF,
blend_dsc.opa);
__arm_2d_impl_src_msk_copy(
(color_int *)src_buf_tmp,
src_stride,
mask_temp_buf,
src_stride,
&copy_size,
(color_int *)dest_buf,
dest_stride,
&copy_size);
lv_mem_buf_release(mask_temp_buf);
}
else {
__arm_2d_impl_src_msk_copy(
(color_int *)src_buf_tmp,
src_stride,
mask_after_rgb,
src_stride,
&copy_size,
(color_int *)dest_buf,
dest_stride,
&copy_size);
}
is_accelerated = true;
)
/* *INDENT-ON* */
}
else if(!mask_any && (cf == LV_IMG_CF_TRUE_COLOR)) {
/* accelerate copy-with-source-masks-and-opacity */
/* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
__PREPARE_LL_ACCELERATION__();
/* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
__PREPARE_LL_ACCELERATION__();
if(blend_dsc.opa >= LV_OPA_MAX) {
__arm_2d_impl_copy(
(color_int *)src_buf_tmp,
src_stride,
(color_int *)dest_buf,
dest_stride,
&copy_size);
}
else {
__arm_2d_impl_alpha_blending(
if(blend_dsc.opa >= LV_OPA_MAX) {
__arm_2d_impl_copy(
(color_int *)src_buf_tmp,
src_stride,
(color_int *)dest_buf,
dest_stride,
&copy_size,
blend_dsc.opa);
}
is_accelerated = true;
)
/* *INDENT-ON* */
&copy_size);
}
else {
__arm_2d_impl_alpha_blending(
(color_int *)src_buf_tmp,
src_stride,
(color_int *)dest_buf,
dest_stride,
&copy_size,
blend_dsc.opa);
}
is_accelerated = true;
)
/* *INDENT-ON* */
}
}
else if(!mask_any
@@ -982,153 +1218,155 @@ static void LV_ATTRIBUTE_FAST_MEM lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_
) {
uint8_t * mask_after_rgb = src_buf + sizeof(lv_color_t) * src_w * src_h;
/* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
/* accelerate transform without re-color */
/* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
/* accelerate transform without re-color */
static arm_2d_tile_t target_tile_origin;
static arm_2d_tile_t target_tile;
arm_2d_region_t clip_region;
static arm_2d_region_t target_region;
static arm_2d_tile_t target_tile_origin;
static arm_2d_tile_t target_tile;
arm_2d_region_t clip_region;
static arm_2d_region_t target_region;
lv_color_t * dest_buf = draw_ctx->buf;
lv_color_t * dest_buf = draw_ctx->buf;
target_tile_origin = (arm_2d_tile_t) {
.tRegion = {
.tSize = {
.iWidth = lv_area_get_width(draw_ctx->buf_area),
.iHeight = lv_area_get_height(draw_ctx->buf_area),
target_tile_origin = (arm_2d_tile_t) {
.tRegion = {
.tSize = {
.iWidth = lv_area_get_width(draw_ctx->buf_area),
.iHeight = lv_area_get_height(draw_ctx->buf_area),
},
},
},
.tInfo.bIsRoot = true,
.phwBuffer = (uint16_t *)draw_ctx->buf,
};
.tInfo.bIsRoot = true,
.phwBuffer = (uint16_t *)draw_ctx->buf,
};
clip_region = (arm_2d_region_t) {
.tLocation = {
.iX = draw_ctx->clip_area->x1 - draw_ctx->buf_area->x1,
.iY = draw_ctx->clip_area->y1 - draw_ctx->buf_area->y1,
},
.tSize = {
.iWidth = lv_area_get_width(draw_ctx->clip_area),
.iHeight = lv_area_get_height(draw_ctx->clip_area),
},
};
arm_2d_tile_generate_child(&target_tile_origin,
&clip_region,
&target_tile,
false);
static arm_2d_tile_t source_tile;
source_tile = (arm_2d_tile_t) {
.tRegion = {
.tSize = {
.iWidth = src_w,
.iHeight = src_h,
clip_region = (arm_2d_region_t) {
.tLocation = {
.iX = draw_ctx->clip_area->x1 - draw_ctx->buf_area->x1,
.iY = draw_ctx->clip_area->y1 - draw_ctx->buf_area->y1,
},
},
.tInfo.bIsRoot = true,
.pchBuffer = (uint8_t *)src_buf,
};
.tSize = {
.iWidth = lv_area_get_width(draw_ctx->clip_area),
.iHeight = lv_area_get_height(draw_ctx->clip_area),
},
};
static arm_2d_location_t source_center, target_center;
source_center.iX = draw_dsc->pivot.x;
source_center.iY = draw_dsc->pivot.y;
arm_2d_tile_generate_child(&target_tile_origin,
&clip_region,
&target_tile,
false);
if(LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf) {
static arm_2d_tile_t source_tile;
__ARM_2D_PREPARE_TRANS_AND_TARGET_REGION(
arm_2d_tile_transform_with_opacity_prepare,
&source_tile,
source_center,
ARM_2D_ANGLE((draw_dsc->angle / 10.0f)),
draw_dsc->zoom / 256.0f,
(color_int)LV_COLOR_CHROMA_KEY.full,
blend_dsc.opa);
source_tile = (arm_2d_tile_t) {
.tRegion = {
.tSize = {
.iWidth = src_w,
.iHeight = src_h,
},
},
.tInfo.bIsRoot = true,
.pchBuffer = (uint8_t *)src_buf,
};
arm_2d_tile_transform(
&target_tile,
&target_region,
NULL
);
is_accelerated = true;
}
else if (LV_IMG_CF_TRUE_COLOR == cf) {
__ARM_2D_PREPARE_TRANS_AND_TARGET_REGION(
arm_2d_tile_transform_only_with_opacity_prepare,
&source_tile,
source_center,
ARM_2D_ANGLE((draw_dsc->angle / 10.0f)),
draw_dsc->zoom / 256.0f,
blend_dsc.opa);
static arm_2d_location_t source_center, target_center;
source_center.iX = draw_dsc->pivot.x;
source_center.iY = draw_dsc->pivot.y;
arm_2d_tile_transform(
&target_tile,
&target_region,
NULL
);
is_accelerated = true;
}
else if (LV_IMG_CF_RGB565A8 == cf) {
static arm_2d_tile_t mask_tile;
mask_tile = source_tile;
if(LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf) {
mask_tile.tInfo.bHasEnforcedColour = true;
mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_COLOUR_GRAY8;
mask_tile.pchBuffer = mask_after_rgb;
__ARM_2D_PREPARE_TRANS_AND_TARGET_REGION(
arm_2d_tile_transform_with_opacity_prepare,
&source_tile,
source_center,
ARM_2D_ANGLE((draw_dsc->angle / 10.0f)),
draw_dsc->zoom / 256.0f,
(color_int)LV_COLOR_CHROMA_KEY.full,
blend_dsc.opa);
__ARM_2D_PREPARE_TRANS_AND_TARGET_REGION(
arm_2d_tile_transform_with_src_mask_and_opacity_prepare,
&source_tile,
&mask_tile,
source_center,
ARM_2D_ANGLE((draw_dsc->angle / 10.0f)),
draw_dsc->zoom / 256.0f,
blend_dsc.opa
arm_2d_tile_transform(
&target_tile,
&target_region,
NULL
);
is_accelerated = true;
}
#if ARM_2D_VERISON >= 10103
else if (LV_IMG_CF_TRUE_COLOR == cf) {
__ARM_2D_PREPARE_TRANS_AND_TARGET_REGION(
arm_2d_tile_transform_only_with_opacity_prepare,
&source_tile,
source_center,
ARM_2D_ANGLE((draw_dsc->angle / 10.0f)),
draw_dsc->zoom / 256.0f,
blend_dsc.opa);
arm_2d_tile_transform(
&target_tile,
&target_region,
NULL
);
is_accelerated = true;
}
#endif
else if (LV_IMG_CF_RGB565A8 == cf) {
static arm_2d_tile_t mask_tile;
mask_tile = source_tile;
mask_tile.tInfo.bHasEnforcedColour = true;
mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_COLOUR_GRAY8;
mask_tile.pchBuffer = mask_after_rgb;
__ARM_2D_PREPARE_TRANS_AND_TARGET_REGION(
arm_2d_tile_transform_with_src_mask_and_opacity_prepare,
&source_tile,
&mask_tile,
source_center,
ARM_2D_ANGLE((draw_dsc->angle / 10.0f)),
draw_dsc->zoom / 256.0f,
blend_dsc.opa
);
arm_2d_tile_transform(
&target_tile,
&target_region,
NULL
);
arm_2d_tile_transform(
&target_tile,
&target_region,
NULL
);
is_accelerated = true;
}
#if defined(__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) \
&& __ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__
else if((LV_IMG_CF_TRUE_COLOR_ALPHA == cf) &&
(LV_COLOR_DEPTH == 32)) {
static arm_2d_tile_t mask_tile;
mask_tile = source_tile;
is_accelerated = true;
}
#if defined(__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) \
&& __ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__
else if((LV_IMG_CF_TRUE_COLOR_ALPHA == cf) &&
(LV_COLOR_DEPTH == 32)) {
static arm_2d_tile_t mask_tile;
mask_tile = source_tile;
mask_tile.tInfo.bHasEnforcedColour = true;
mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_CHANNEL_8in32;
mask_tile.pchBuffer += 3;
mask_tile.tInfo.bHasEnforcedColour = true;
mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_CHANNEL_8in32;
mask_tile.pchBuffer += 3;
__ARM_2D_PREPARE_TRANS_AND_TARGET_REGION(
arm_2d_tile_transform_with_src_mask_and_opacity_prepare,
&source_tile,
&mask_tile,
source_center,
ARM_2D_ANGLE((draw_dsc->angle / 10.0f)),
draw_dsc->zoom / 256.0f,
blend_dsc.opa
);
__ARM_2D_PREPARE_TRANS_AND_TARGET_REGION(
arm_2d_tile_transform_with_src_mask_and_opacity_prepare,
&source_tile,
&mask_tile,
source_center,
ARM_2D_ANGLE((draw_dsc->angle / 10.0f)),
draw_dsc->zoom / 256.0f,
blend_dsc.opa
arm_2d_tile_transform(
&target_tile,
&target_region,
NULL
);
arm_2d_tile_transform(
&target_tile,
&target_region,
NULL
);
is_accelerated = true;
}
#endif
)
/* *INDENT-ON* */
is_accelerated = true;
}
#endif
)
/* *INDENT-ON* */
}
/* *INDENT-OFF* */
@@ -1206,6 +1444,7 @@ static void lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx)
lv_draw_sw_wait_for_finish(draw_ctx);
}
#endif
/**********************
* STATIC FUNCTIONS

View File

@@ -23,4 +23,3 @@ 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
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nema_gfx/lv_draw_nema_gfx.mk

View File

@@ -1,554 +0,0 @@
/**
* @file lv_draw_nema_gfx.c
*
*/
/**
* MIT License
*
* -----------------------------------------------------------------------------
* Copyright (c) 2008-24 Think Silicon Single Member PC
* -----------------------------------------------------------------------------
*
* 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 "../../core/lv_refr.h"
#if LV_USE_NEMA_GFX
#include "lv_draw_nema_gfx.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static lv_res_t draw_nema_gfx_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
static inline bool Isargb8565(lv_img_cf_t cf);
static uint32_t lv_cf_to_nema(lv_img_cf_t cf);
static uint32_t skip_pallete(lv_img_cf_t cf);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_nema_gfx_init(void)
{
nema_init();
return;
}
static inline bool Isargb8565(lv_img_cf_t cf)
{
#if LV_COLOR_DEPTH != 32
if(cf == LV_IMG_CF_TRUE_COLOR_ALPHA)
return true;
#endif
return false;
}
static uint32_t lv_cf_to_nema(lv_img_cf_t cf)
{
switch(cf) {
case LV_IMG_CF_ALPHA_1BIT:
return NEMA_A1;
case LV_IMG_CF_ALPHA_2BIT:
return NEMA_A2;
case LV_IMG_CF_ALPHA_4BIT:
return NEMA_A4;
case LV_IMG_CF_ALPHA_8BIT:
return NEMA_A8;
case LV_IMG_CF_INDEXED_1BIT:
return NEMA_L1;
case LV_IMG_CF_INDEXED_2BIT:
return NEMA_L2;
case LV_IMG_CF_INDEXED_4BIT:
return NEMA_L4;
case LV_IMG_CF_INDEXED_8BIT:
return NEMA_L8;
default:
return LV_NEMA_GFX_COLOR_FORMAT;
}
}
static uint32_t skip_pallete(lv_img_cf_t cf)
{
switch(cf) {
case LV_IMG_CF_INDEXED_1BIT:
return 2;
case LV_IMG_CF_INDEXED_2BIT:
return 4;
case LV_IMG_CF_INDEXED_4BIT:
return 16;
default:
return 256;
}
}
void lv_draw_nema_gfx_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);
bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
bool transform = dsc->angle != 0 || dsc->zoom != LV_IMG_ZOOM_NONE ? true : false;
lv_draw_nema_gfx_ctx_t * nema_gfx_draw_ctx = (lv_draw_nema_gfx_ctx_t *)draw_ctx;
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);
lv_coord_t tex_w = lv_area_get_width(coords);
lv_coord_t tex_h = lv_area_get_height(coords);
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_ctx->clip_area);
lv_area_move(&clip_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 || Isargb8565(cf)) {
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);
uint32_t blending_mode = NEMA_BL_SIMPLE;
uint32_t color_format = lv_cf_to_nema(cf);
nema_buffer_t Shuffle_pallete_bo;
if(color_format == NEMA_L8) {
Shuffle_pallete_bo = nema_buffer_create(256 * 4);
uint32_t * Shuffle_pallete = Shuffle_pallete_bo.base_virt;
for(int i = 0; i < 256; i++) {
int idx = ((i >> 4) | ((i & 0xfU) << 4));
lv_color32_t col32 = {.full = lv_color_to32(*(lv_color_t *)((uint32_t *)src_buf + idx))};
Shuffle_pallete[i] = col32.full;
}
}
if(!mask_any) {
nema_bind_dst_tex((uintptr_t)NEMA_VIRT2PHYS(draw_ctx->buf), lv_area_get_width(draw_ctx->buf_area),
lv_area_get_height(draw_ctx->buf_area), LV_NEMA_GFX_COLOR_FORMAT,
lv_area_get_width(draw_ctx->buf_area)*LV_NEMA_GFX_FORMAT_MULTIPLIER);
nema_set_clip(clip_area.x1, clip_area.y1, lv_area_get_width(&clip_area), lv_area_get_height(&clip_area));
if(color_format == NEMA_L1 || color_format == NEMA_L2 || color_format == NEMA_L4) {
blending_mode |= NEMA_BLOP_LUT;
nema_bind_lut_tex((uintptr_t)((uint32_t *)src_buf + (skip_pallete(cf))), tex_w, tex_h, color_format, -1, 0,
(uintptr_t)(src_buf), NEMA_BGRA8888);
}
else if(color_format == NEMA_L8) {
blending_mode |= NEMA_BLOP_LUT;
nema_bind_lut_tex((uintptr_t)((uint32_t *)src_buf + (skip_pallete(cf))), tex_w, tex_h, color_format, -1, 0,
Shuffle_pallete_bo.base_phys, NEMA_BGRA8888);
}
else
nema_bind_src_tex((uintptr_t)(src_buf), tex_w, tex_h, color_format, -1,
(dsc->antialias == true) ? NEMA_FILTER_BL : NEMA_FILTER_PS);
if(recolor) {
lv_color32_t col32 = {.full = lv_color_to32(dsc->recolor)};
uint32_t color = nema_rgba(col32.ch.red, col32.ch.green, col32.ch.blue, dsc->recolor_opa);
nema_set_recolor_color(color);
blending_mode |= NEMA_BLOP_RECOLOR;
}
if(lv_img_cf_is_chroma_keyed(cf)) {
blending_mode |= NEMA_BLOP_SRC_CKEY;
lv_color_t ckey = LV_COLOR_CHROMA_KEY;
lv_color32_t col32 = {.full = lv_color_to32(ckey)};
uint32_t src_color_key = nema_rgba(col32.ch.red, col32.ch.green, col32.ch.blue, 0U);
nema_set_src_color_key(src_color_key);
}
if(dsc->opa < 255) {
uint32_t rgba = ((uint32_t)dsc->opa << 24U) | ((uint32_t)dsc->opa << 16U) | ((uint32_t)dsc->opa << 8U) | ((
uint32_t)dsc->opa);
nema_set_const_color(rgba);
blending_mode |= NEMA_BLOP_MODULATE_A;
}
nema_set_blend_blit(blending_mode);
if(!transform) {
nema_blit_rect((coords->x1 - draw_ctx->buf_area->x1),
(coords->y1 - draw_ctx->buf_area->y1), tex_w, tex_h);
}
else {
/*Calculate the transformed points*/
float x0 = (coords->x1 - draw_ctx->buf_area->x1);
float y0 = (coords->y1 - draw_ctx->buf_area->y1);
float x1 = x0 + tex_w ;
float y1 = y0;
float x2 = x0 + tex_w ;
float y2 = y0 + tex_h;
float x3 = x0 ;
float y3 = y0 + tex_h;
nema_matrix3x3_t m;
nema_mat3x3_load_identity(m);
nema_mat3x3_translate(m, -x0, -y0);
nema_mat3x3_translate(m, -(float)dsc->pivot.x, -(float)dsc->pivot.y);
nema_mat3x3_rotate(m, (dsc->angle / 10.0f)); /* angle is 1/10 degree */
float scale = 1.f * dsc->zoom / LV_IMG_ZOOM_NONE;
nema_mat3x3_scale(m, (float)scale, (float)scale);
nema_mat3x3_translate(m, (float)dsc->pivot.x, (float)dsc->pivot.y);
nema_mat3x3_translate(m, x0, y0);
/*Apply Transformation Matrix to Vertices*/
nema_mat3x3_mul_vec(m, &x0, &y0);
nema_mat3x3_mul_vec(m, &x1, &y1);
nema_mat3x3_mul_vec(m, &x2, &y2);
nema_mat3x3_mul_vec(m, &x3, &y3);
nema_blit_quad_fit(x0, y0,
x1, y1,
x2, y2,
x3, y3);
}
nema_cl_submit(&(nema_gfx_draw_ctx->cl));
if(color_format == NEMA_L8) {
nema_cl_wait(&(nema_gfx_draw_ctx->cl));
nema_buffer_destroy(&Shuffle_pallete_bo);
}
return;
}
/*Wait for GPU to finish previous jobs in case of failure and call SW rendering*/
nema_cl_wait(&(nema_gfx_draw_ctx->cl));
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
return;
}
void lv_draw_nema_gfx_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
{
lv_draw_sw_init_ctx(drv, draw_ctx);
lv_draw_nema_gfx_ctx_t * nema_gfx_draw_ctx = (lv_draw_nema_gfx_ctx_t *)draw_ctx;
nema_gfx_draw_ctx->base_sw_ctx.blend = lv_draw_nema_gfx_blend;
nema_gfx_draw_ctx->base_sw_ctx.base_draw.draw_rect = lv_draw_nema_gfx_rect;
nema_gfx_draw_ctx->base_sw_ctx.base_draw.draw_bg = lv_draw_nema_gfx_bg;
nema_gfx_draw_ctx->base_sw_ctx.base_draw.draw_img_decoded = lv_draw_nema_gfx_img_decoded;
nema_gfx_draw_ctx->base_sw_ctx.base_draw.draw_img = lv_draw_nema_gfx_img;
nema_gfx_draw_ctx->base_sw_ctx.base_draw.draw_letter = lv_draw_nema_gfx_letter;
//Overide this functions to wait for GPU
nema_gfx_draw_ctx->base_sw_ctx.base_draw.draw_arc = lv_draw_nema_gfx_arc;
nema_gfx_draw_ctx->base_sw_ctx.base_draw.draw_line = lv_draw_nema_gfx_line;
nema_gfx_draw_ctx->base_sw_ctx.base_draw.draw_polygon = lv_draw_nema_gfx_polygon;
/*Create GPU Command List*/
nema_gfx_draw_ctx->cl = nema_cl_create();
/*Bind Command List*/
nema_cl_bind_circular(&(nema_gfx_draw_ctx->cl));
}
void lv_draw_nema_gfx_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
{
LV_UNUSED(drv);
lv_draw_nema_gfx_ctx_t * nema_gfx_draw_ctx = (lv_draw_nema_gfx_ctx_t *) draw_ctx;
nema_cl_destroy(&(nema_gfx_draw_ctx->cl));
}
void lv_draw_nema_gfx_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
{
const lv_opa_t * mask;
if(dsc->mask_buf == NULL) mask = NULL;
if(dsc->mask_buf && dsc->mask_res == LV_DRAW_MASK_RES_TRANSP) return;
else if(dsc->mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask = NULL;
else mask = dsc->mask_buf;
lv_draw_nema_gfx_ctx_t * nema_gfx_draw_ctx = (lv_draw_nema_gfx_ctx_t *)draw_ctx;
lv_area_t blend_area;
bool render_on_gpu = false;
/*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);
if(mask == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL) {
const lv_color_t * src_buf = dsc->src_buf;
nema_bind_dst_tex((uintptr_t)NEMA_VIRT2PHYS(draw_ctx->buf), lv_area_get_width(draw_ctx->buf_area),
lv_area_get_height(draw_ctx->buf_area), LV_NEMA_GFX_COLOR_FORMAT,
lv_area_get_width(draw_ctx->buf_area)*LV_NEMA_GFX_FORMAT_MULTIPLIER);
//Set Clipping Area
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_ctx->clip_area);
lv_area_move(&clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
nema_set_clip(clip_area.x1, clip_area.y1, lv_area_get_width(&clip_area), lv_area_get_height(&clip_area));
lv_coord_t coords_bg_w = lv_area_get_width(&blend_area);
lv_coord_t coords_bg_h = lv_area_get_height(&blend_area);
if(src_buf == NULL) {
//Simple Fill
uint8_t opacity;
lv_color32_t col32 = {.full = lv_color_to32(dsc->color)};
if(dsc->opa < LV_OPA_MAX && dsc->opa > LV_OPA_MIN) {
opacity = (uint8_t)(((uint16_t)col32.ch.alpha * dsc->opa) >> 8);
}
else if(dsc->opa >= LV_OPA_MAX) {
opacity = col32.ch.alpha;
}
uint32_t color = nema_rgba(col32.ch.red, col32.ch.green, col32.ch.blue, opacity);
if(opacity < 255U)
nema_set_blend_fill(NEMA_BL_SRC_OVER | NEMA_BLOP_SRC_PREMULT);
else
nema_set_blend_fill(NEMA_BL_SRC_OVER);
nema_fill_rect(blend_area.x1, blend_area.y1, coords_bg_w, coords_bg_h, color);
render_on_gpu = true;
}
else { //Full Opaque mask
nema_bind_src_tex((uintptr_t)(src_buf), coords_bg_w, coords_bg_h, LV_NEMA_GFX_COLOR_FORMAT,
coords_bg_w * LV_NEMA_GFX_FORMAT_MULTIPLIER, NEMA_FILTER_PS);
if(dsc->opa < 255) {
uint32_t rgba = ((uint32_t)dsc->opa << 24U) | ((uint32_t)dsc->opa << 16U) | ((uint32_t)dsc->opa << 8U) | ((
uint32_t)dsc->opa);
nema_set_const_color(rgba);
nema_set_blend_blit(NEMA_BL_SIMPLE | NEMA_BLOP_MODULATE_A);
}
else
nema_set_blend_blit(NEMA_BL_SIMPLE);
nema_blit_rect(blend_area.x1, blend_area.y1, coords_bg_w, coords_bg_h);
render_on_gpu = true;
}
}
if(render_on_gpu) {
nema_cl_submit(&(nema_gfx_draw_ctx->cl));
}
else {
nema_cl_wait(&(nema_gfx_draw_ctx->cl));
lv_draw_sw_blend_basic(draw_ctx, dsc);
}
return;
}
void lv_draw_nema_gfx_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 nema_dsc;
lv_memcpy(&nema_dsc, dsc, sizeof(nema_dsc));
#if LV_DRAW_COMPLEX
/* Draw only the shadow */
nema_dsc.bg_opa = 0;
nema_dsc.bg_img_opa = 0;
nema_dsc.border_opa = 0;
nema_dsc.outline_opa = 0;
lv_draw_nema_gfx_ctx_t * nema_gfx_draw_ctx = (lv_draw_nema_gfx_ctx_t *)draw_ctx;
nema_cl_wait(&(nema_gfx_draw_ctx->cl));
lv_draw_sw_rect(draw_ctx, &nema_dsc, coords);
/* Draw the background */
nema_dsc.shadow_opa = 0;
nema_dsc.bg_opa = dsc->bg_opa;
if(draw_nema_gfx_bg(draw_ctx, &nema_dsc, coords) == LV_RES_OK) {
nema_dsc.bg_opa = 0;
}
#endif /*LV_DRAW_COMPLEX*/
/* Draw the remaining parts */
nema_dsc.bg_img_opa = dsc->bg_img_opa;
nema_dsc.border_opa = dsc->border_opa;
nema_dsc.outline_opa = dsc->outline_opa;
lv_draw_sw_rect(draw_ctx, &nema_dsc, coords);
}
void lv_draw_nema_gfx_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
{
bool rendered_by_gpu = false;
lv_draw_rect_dsc_t nema_dsc;
lv_memcpy(&nema_dsc, dsc, sizeof(nema_dsc));
// try to render with GPU
rendered_by_gpu = (draw_nema_gfx_bg(draw_ctx, &nema_dsc, coords) == LV_RES_OK);
if(rendered_by_gpu) {
// rendered with gpu
// continuew with the rest
nema_dsc.bg_opa = 0;
lv_draw_sw_bg(draw_ctx, &nema_dsc, coords);
}
else {
// couldn't draw with gpu
lv_draw_sw_bg(draw_ctx, dsc, coords);
}
}
lv_res_t draw_nema_gfx_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
{
#if LV_COLOR_SCREEN_TRANSP && LV_COLOR_DEPTH == 32
lv_memset_00(draw_ctx->buf, lv_area_get_size(draw_ctx->buf_area) * sizeof(lv_color_t));
#endif
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;
/*Make the blend area relative to the buffer*/
lv_area_move(&bg_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_draw_nema_gfx_ctx_t * nema_gfx_draw_ctx = (lv_draw_nema_gfx_ctx_t *)draw_ctx;
nema_bind_dst_tex((uintptr_t)NEMA_VIRT2PHYS(draw_ctx->buf), lv_area_get_width(draw_ctx->buf_area),
lv_area_get_height(draw_ctx->buf_area), LV_NEMA_GFX_COLOR_FORMAT,
lv_area_get_width(draw_ctx->buf_area)*LV_NEMA_GFX_FORMAT_MULTIPLIER);
//Set Clipping Area
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_ctx->clip_area);
lv_area_move(&clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
nema_set_clip(clip_area.x1, clip_area.y1, lv_area_get_width(&clip_area), lv_area_get_height(&clip_area));
lv_coord_t coords_bg_w = lv_area_get_width(&bg_coords);
lv_coord_t coords_bg_h = lv_area_get_height(&bg_coords);
int32_t short_side = LV_MIN(coords_bg_w, coords_bg_h);
int32_t radius = LV_MIN(dsc->radius, short_side >> 1);
bool mask_any = lv_draw_mask_is_any(&bg_coords);
if(!mask_any && (dsc->bg_grad.dir == LV_GRAD_DIR_NONE)) {
uint8_t opacity;
lv_color32_t bg_col32 = {.full = lv_color_to32(dsc->bg_color)};
if(dsc->bg_opa < LV_OPA_MAX && dsc->bg_opa > LV_OPA_MIN) {
opacity = (uint8_t)(((uint16_t)bg_col32.ch.alpha * dsc->bg_opa) >> 8);
}
else if(dsc->bg_opa >= LV_OPA_MAX) {
opacity = bg_col32.ch.alpha;
}
if(opacity < 255U) {
nema_set_blend_fill(NEMA_BL_SIMPLE);
}
else {
nema_set_blend_fill(NEMA_BL_SRC);
}
uint32_t bg_color = nema_rgba(bg_col32.ch.red, bg_col32.ch.green, bg_col32.ch.blue, opacity);
if(dsc->radius != 0)
nema_fill_rounded_rect_aa(bg_coords.x1, bg_coords.y1, coords_bg_w, coords_bg_h, radius, bg_color);
else
nema_fill_rect(bg_coords.x1, bg_coords.y1, coords_bg_w, coords_bg_h, bg_color);
nema_cl_submit(&(nema_gfx_draw_ctx->cl));
nema_cl_wait(&(nema_gfx_draw_ctx->cl));
return LV_RES_OK;
}
return LV_RES_INV;
}
LV_ATTRIBUTE_FAST_MEM void lv_draw_nema_gfx_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)
{
lv_draw_nema_gfx_ctx_t * nema_gfx_draw_ctx = (lv_draw_nema_gfx_ctx_t *)draw_ctx;
//Ensure that GPU has no unfinished workload
nema_cl_wait(&(nema_gfx_draw_ctx->cl));
lv_draw_sw_line(draw_ctx, dsc, point1, point2);
}
void lv_draw_nema_gfx_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)
{
lv_draw_nema_gfx_ctx_t * nema_gfx_draw_ctx = (lv_draw_nema_gfx_ctx_t *)draw_ctx;
//Ensure that GPU has no unfinished workload
nema_cl_wait(&(nema_gfx_draw_ctx->cl));
lv_draw_sw_polygon(draw_ctx, draw_dsc, points, point_cnt);
}
void lv_draw_nema_gfx_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_nema_gfx_ctx_t * nema_gfx_draw_ctx = (lv_draw_nema_gfx_ctx_t *)draw_ctx;
//Ensure that GPU has no unfinished workload
nema_cl_wait(&(nema_gfx_draw_ctx->cl));
lv_draw_sw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle);
}
#endif

View File

@@ -1,134 +0,0 @@
/**
* @file lv_draw_nema_gfx.h
*
*/
/**
* MIT License
*
* -----------------------------------------------------------------------------
* Copyright (c) 2008-24 Think Silicon Single Member PC
* -----------------------------------------------------------------------------
*
* 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_NEMA_GFX_H
#define LV_DRAW_NEMA_GFX_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_NEMA_GFX
#include "nema_core.h"
#include "nema_utils.h"
#include "nema_error.h"
#include "nema_provisional.h"
/*********************
* DEFINES
*********************/
#ifndef NEMA_VIRT2PHYS
#define NEMA_VIRT2PHYS
#endif
/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
#if LV_COLOR_DEPTH == 8
#define LV_NEMA_GFX_COLOR_FORMAT NEMA_RGB332
#define LV_NEMA_GFX_FORMAT_MULTIPLIER 1
#elif LV_COLOR_DEPTH == 16
#define LV_NEMA_GFX_COLOR_FORMAT NEMA_RGB565
#define LV_NEMA_GFX_FORMAT_MULTIPLIER 2
#elif LV_COLOR_DEPTH == 32
#define LV_NEMA_GFX_COLOR_FORMAT NEMA_BGRA8888
#define LV_NEMA_GFX_FORMAT_MULTIPLIER 4
#else
/*Can't use GPU with other formats*/
#endif
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_draw_sw_ctx_t base_sw_ctx;
/*Add other needed fields here*/
nema_cmdlist_t cl;
} lv_draw_nema_gfx_ctx_t;
struct _lv_disp_drv_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_nema_gfx_init(void);
void lv_draw_nema_gfx_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_nema_gfx_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_nema_gfx_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
void lv_draw_nema_gfx_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
void lv_draw_nema_gfx_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
void lv_draw_nema_gfx_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);
void lv_draw_nema_gfx_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_nema_gfx_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_nema_gfx_line(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc,
const lv_point_t * point1, const lv_point_t * point2);
void lv_draw_nema_gfx_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);
lv_res_t lv_draw_nema_gfx_img(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
const lv_area_t * coords,
const void * src);
/**********************
* MACROS
**********************/
#endif /*LV_USE_NEMA_GFX*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_NEMA_GFX_H*/

View File

@@ -1,8 +0,0 @@
CSRCS += lv_draw_nema_gfx.c
CSRCS += lv_draw_nema_gfx_letter.c
CSRCS += lv_draw_nema_gfx_img.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nema_gfx
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nema_gfx
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nema_gfx"

View File

@@ -1,243 +0,0 @@
/**
* @file lv_draw_nema_gfx_img.c
*
*/
/**
* MIT License
*
* -----------------------------------------------------------------------------
* Copyright (c) 2008-24 Think Silicon Single Member PC
* -----------------------------------------------------------------------------
*
* 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 "../../core/lv_refr.h"
#if LV_USE_NEMA_GFX
#include "lv_draw_nema_gfx.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"
#include "lv_img_buf.h"
#include "../misc/lv_style.h"
/**********************
* STATIC PROTOTYPES
**********************/
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);
/**********************
* GLOBAL FUNCTIONS
**********************/
bool lv_img_cf_alpha_only_format(lv_img_cf_t cf)
{
bool is_alpha_format = false;
switch(cf) {
case LV_IMG_CF_ALPHA_1BIT:
case LV_IMG_CF_ALPHA_2BIT:
case LV_IMG_CF_ALPHA_4BIT:
case LV_IMG_CF_ALPHA_8BIT:
is_alpha_format = true;
break;
default:
is_alpha_format = false;
break;
}
return is_alpha_format;
}
bool lv_img_cf_lut_format(lv_img_cf_t cf)
{
bool is_lut_format = false;
switch(cf) {
case LV_IMG_CF_INDEXED_1BIT:
case LV_IMG_CF_INDEXED_2BIT:
case LV_IMG_CF_INDEXED_4BIT:
case LV_IMG_CF_INDEXED_8BIT:
is_lut_format = true;
break;
default:
is_lut_format = false;
break;
}
return is_lut_format;
}
lv_res_t lv_draw_nema_gfx_img(struct _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_img_cf_alpha_only_format(cdsc->dec_dsc.header.cf)) ||
lv_img_cf_lut_format(cdsc->dec_dsc.header.cf)) {
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;
}
if(lv_img_cf_alpha_only_format(cdsc->dec_dsc.header.cf)) {
lv_color32_t tex_col32 = {.full = lv_color_to32(cdsc->dec_dsc.color)};
uint32_t tex_color = nema_rgba(tex_col32.ch.red, tex_col32.ch.green, tex_col32.ch.blue, 0);
nema_set_tex_color(tex_color);
cf = cdsc->dec_dsc.header.cf;
}
if(lv_img_cf_lut_format(cdsc->dec_dsc.header.cf)) {
cf = cdsc->dec_dsc.header.cf;
}
const lv_area_t * clip_area_ori = draw_ctx->clip_area;
draw_ctx->clip_area = &clip_com;
uint8_t * img_data = (uint8_t *)(cdsc->dec_dsc.img_data) ? (uint8_t *)(cdsc->dec_dsc.img_data) : (uint8_t *)(((
lv_img_dsc_t *)src)->data);
lv_draw_img_decoded(draw_ctx, draw_dsc, coords, 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) {
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
}
#endif

View File

@@ -1,330 +0,0 @@
/**
* @file lv_draw_nema_gfx_letter.c
*
*/
/**
* MIT License
*
* -----------------------------------------------------------------------------
* Copyright (c) 2008-24 Think Silicon Single Member PC
* -----------------------------------------------------------------------------
*
* 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 "../../hal/lv_hal_disp.h"
#include "../../misc/lv_math.h"
#include "../../misc/lv_assert.h"
#include "../../misc/lv_area.h"
#include "../../misc/lv_style.h"
#include "../../font/lv_font.h"
#include "../../core/lv_refr.h"
#include "lv_draw_nema_gfx.h"
#if LV_USE_NEMA_GFX
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* FORWARD DECLARATION
**********************/
void nema_raster_rect(int x, int y, int w, int h);
void nema_set_matrix(nema_matrix3x3_t m);
/**********************
* STATIC PROTOTYPES
**********************/
LV_ATTRIBUTE_FAST_MEM static lv_res_t draw_nema_gfx_letter_normal(lv_draw_ctx_t * draw_ctx,
const lv_draw_label_dsc_t * dsc,
const lv_point_t * pos, lv_font_glyph_dsc_t * g, const uint8_t * map_p);
LV_ATTRIBUTE_FAST_MEM static lv_res_t draw_nema_gfx_letter_blend(lv_draw_ctx_t * draw_ctx,
const lv_draw_sw_blend_dsc_t * dsc, lv_font_glyph_dsc_t * g);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* GLOBAL VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Draw a letter in the Virtual Display Buffer
* @param pos_p left-top coordinate of the latter
* @param mask_p the letter will be drawn only on this area (truncated to draw_buf area)
* @param font_p pointer to font
* @param letter a letter to draw
* @param color color of letter
* @param opa opacity of letter (0..255)
*/
void lv_draw_nema_gfx_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
uint32_t letter)
{
lv_font_glyph_dsc_t g;
bool g_ret = lv_font_get_glyph_dsc(dsc->font, &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+%" PRIX32, letter);
#if LV_USE_FONT_PLACEHOLDER
/* 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);
#endif
}
return;
}
/*Don't draw anything if the character is empty. E.g. space*/
if((g.box_h == 0) || (g.box_w == 0)) return;
lv_point_t gpos;
gpos.x = pos_p->x + g.ofs_x;
gpos.y = pos_p->y + (dsc->font->line_height - dsc->font->base_line) - g.box_h - g.ofs_y;
/*If the letter is completely out of mask don't draw it*/
if(gpos.x + g.box_w < draw_ctx->clip_area->x1 ||
gpos.x > draw_ctx->clip_area->x2 ||
gpos.y + g.box_h < draw_ctx->clip_area->y1 ||
gpos.y > draw_ctx->clip_area->y2) {
return;
}
if(g.resolved_font->subpx) {
#if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX
return lv_draw_sw_letter(draw_ctx, dsc, pos_p, letter);
#else
LV_LOG_WARN("Can't draw sub-pixel rendered letter because LV_USE_FONT_SUBPX == 0 in lv_conf.h");
return ;
#endif
}
const uint8_t * map_p = lv_font_get_glyph_bitmap(g.resolved_font, letter);
if(map_p == NULL) {
LV_LOG_WARN("lv_draw_letter: character's bitmap not found");
return;
}
if(draw_nema_gfx_letter_normal(draw_ctx, dsc, &gpos, &g, map_p) != LV_RES_OK)
return lv_draw_sw_letter(draw_ctx, dsc, pos_p, letter);
}
/**********************
* STATIC FUNCTIONS
**********************/
LV_ATTRIBUTE_FAST_MEM static lv_res_t draw_nema_gfx_letter_normal(lv_draw_ctx_t * draw_ctx,
const lv_draw_label_dsc_t * dsc,
const lv_point_t * pos, lv_font_glyph_dsc_t * g, const uint8_t * map_p)
{
uint32_t bpp = g->bpp;
lv_opa_t opa = dsc->opa;
if(bpp == 3) bpp = 4;
#if LV_USE_IMGFONT
if(bpp == LV_IMGFONT_BPP) { //is imgfont
lv_area_t fill_area;
fill_area.x1 = pos->x;
fill_area.y1 = pos->y;
fill_area.x2 = pos->x + g->box_w - 1;
fill_area.y2 = pos->y + g->box_h - 1;
lv_draw_img_dsc_t img_dsc;
lv_draw_img_dsc_init(&img_dsc);
img_dsc.angle = 0;
img_dsc.zoom = LV_IMG_ZOOM_NONE;
img_dsc.opa = dsc->opa;
img_dsc.blend_mode = dsc->blend_mode;
lv_draw_img(draw_ctx, &img_dsc, &fill_area, map_p);
return;
}
#endif
int32_t box_w = g->box_w;
int32_t box_h = g->box_h;
/*Calculate the col/row start/end on the map*/
int32_t col_start = pos->x >= draw_ctx->clip_area->x1 ? 0 : draw_ctx->clip_area->x1 - pos->x;
int32_t col_end = pos->x + box_w <= draw_ctx->clip_area->x2 ? box_w : draw_ctx->clip_area->x2 - pos->x + 1;
int32_t row_start = pos->y >= draw_ctx->clip_area->y1 ? 0 : draw_ctx->clip_area->y1 - pos->y;
int32_t row_end = pos->y + box_h <= draw_ctx->clip_area->y2 ? box_h : draw_ctx->clip_area->y2 - pos->y + 1;
lv_draw_sw_blend_dsc_t blend_dsc;
lv_memset_00(&blend_dsc, sizeof(blend_dsc));
blend_dsc.color = dsc->color;
blend_dsc.opa = dsc->opa;
blend_dsc.blend_mode = dsc->blend_mode;
lv_coord_t hor_res = lv_disp_get_hor_res(_lv_refr_get_disp_refreshing());
uint32_t mask_buf_size = box_w * box_h > hor_res ? hor_res : box_w * box_h;
blend_dsc.mask_buf = (uint8_t *)map_p;
/*Initially leave fill area as is, to check for mask_area*/
lv_area_t fill_area;
fill_area.x1 = col_start + pos->x;
fill_area.x2 = col_end + pos->x - 1;
fill_area.y1 = row_start + pos->y;
fill_area.y2 = row_end + pos->y - 1;
#if LV_DRAW_COMPLEX
lv_coord_t fill_w = lv_area_get_width(&fill_area);
lv_area_t mask_area;
lv_area_copy(&mask_area, &fill_area);
mask_area.y2 = mask_area.y1 + row_end;
bool mask_any = lv_draw_mask_is_any(&mask_area);
#endif
/*After the mask checking change fill area to what NemaGFX wants*/
fill_area.x1 = pos->x;
fill_area.y1 = pos->y;
blend_dsc.blend_area = &fill_area;
blend_dsc.mask_area = &fill_area;
#if LV_DRAW_COMPLEX
/*Apply masks if any*/
if(mask_any) {
return LV_RES_INV;
}
#endif
lv_res_t result = draw_nema_gfx_letter_blend(draw_ctx, &blend_dsc, g);
return result;
}
static inline uint8_t _bpp_nema_gfx_format(lv_font_glyph_dsc_t * g)
{
uint32_t bpp = g->bpp ;
if(bpp == 3) bpp = 4;
switch(bpp) {
case 1:
return NEMA_A1;
case 2:
return NEMA_A2;
case 4:
return NEMA_A4;
default:
return NEMA_A8;
}
}
LV_ATTRIBUTE_FAST_MEM static lv_res_t draw_nema_gfx_letter_blend(lv_draw_ctx_t * draw_ctx,
const lv_draw_sw_blend_dsc_t * dsc, lv_font_glyph_dsc_t * g)
{
lv_draw_nema_gfx_ctx_t * nema_gfx_draw_ctx = (lv_draw_nema_gfx_ctx_t *)draw_ctx;
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 LV_RES_OK; /*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);
nema_bind_dst_tex((uintptr_t)NEMA_VIRT2PHYS(draw_ctx->buf), lv_area_get_width(draw_ctx->buf_area),
lv_area_get_height(draw_ctx->buf_area), LV_NEMA_GFX_COLOR_FORMAT,
lv_area_get_width(draw_ctx->buf_area)*LV_NEMA_GFX_FORMAT_MULTIPLIER);
//Set Clipping Area
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_ctx->clip_area);
lv_area_move(&clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
nema_set_clip(clip_area.x1, clip_area.y1, lv_area_get_width(&clip_area), lv_area_get_height(&clip_area));
uint8_t opacity;
lv_color32_t col32 = {.full = lv_color_to32(dsc->color)};
if(dsc->opa < LV_OPA_MAX && dsc->opa > LV_OPA_MIN) {
opacity = (uint8_t)(((uint16_t)col32.ch.alpha * dsc->opa) >> 8);
}
else if(dsc->opa >= LV_OPA_MAX) {
opacity = col32.ch.alpha;
}
uint32_t color = nema_rgba(col32.ch.red, col32.ch.green, col32.ch.blue, opacity);
nema_set_tex_color(color);
lv_coord_t x = dsc->blend_area->x1;
lv_coord_t y = dsc->blend_area->y1;
lv_coord_t w = g->box_w;
lv_coord_t h = g->box_h;
nema_bind_src_tex((uintptr_t)(dsc->mask_buf), w * h, 1, _bpp_nema_gfx_format(g), -1, 1);
if(opacity < 255U) {
nema_set_blend_blit(NEMA_BL_SIMPLE | NEMA_BLOP_MODULATE_A);
nema_set_const_color(color);
}
else {
nema_set_blend_blit(NEMA_BL_SIMPLE);
}
nema_matrix3x3_t m = {
1, w, -x - (y * w) - (0.5 * w),
0, 1, 0,
0, 0, 1
};
nema_set_matrix(m);
nema_raster_rect(x, y, w, h);
nema_cl_submit(&(nema_gfx_draw_ctx->cl));
return LV_RES_OK;
}
#endif

View File

@@ -45,7 +45,7 @@ static lv_res_t find_oldest_item_life(lv_grad_t * c, void * ctx);
static lv_res_t kill_oldest_item(lv_grad_t * c, void * ctx);
static lv_res_t find_item(lv_grad_t * c, void * ctx);
static void free_item(lv_grad_t * c);
static uint32_t compute_key(const lv_grad_dsc_t * g, lv_coord_t size, lv_coord_t w);
static uint32_t compute_key(const lv_grad_dsc_t * g, lv_coord_t w, lv_coord_t h);
/**********************
* STATIC VARIABLE
@@ -56,22 +56,16 @@ static uint8_t * grad_cache_end = 0;
/**********************
* STATIC FUNCTIONS
**********************/
union void_cast {
const void * ptr;
const uint32_t value;
};
static uint32_t compute_key(const lv_grad_dsc_t * g, lv_coord_t size, lv_coord_t w)
{
uint32_t key =
((uint32_t) g->stops_count) |
(((uint32_t) g->dir) << 8) |
(((uint32_t) g->dither) << 16);
uint32_t frac_product = 1;
for(uint8_t i = 0; i < g->stops_count; i++) {
key ^= (uint32_t) g->stops[i].color.full;
frac_product *= ((uint32_t) g->stops[i].frac) + 1;
}
key ^= frac_product;
key ^= (uint32_t) size;
key ^= ((uint32_t) w) >> 1; /*Yes, this is correct, it's like a hash that changes if the width changes*/
return key;
union void_cast v;
v.ptr = g;
return (v.value ^ size ^ (w >> 1)); /*Yes, this is correct, it's like a hash that changes if the width changes*/
}
static size_t get_cache_item_size(lv_grad_t * c)

View File

@@ -288,12 +288,8 @@ static void flex_update(lv_obj_t * cont, void * user_data)
}
children_repos(cont, &f, track_first_item, next_track_first_item, abs_x, abs_y, max_main_size, item_gap, &t);
track_first_item = next_track_first_item;
if(t.grow_dsc) {
lv_mem_buf_release(t.grow_dsc);
}
lv_mem_buf_release(t.grow_dsc);
t.grow_dsc = NULL;
if(rtl && !f.row) {
*cross_pos -= gap + track_gap;
}

View File

@@ -28,7 +28,6 @@ static lv_res_t decoder_info(struct _lv_img_decoder_t * decoder, const void * sr
static lv_res_t decoder_open(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc);
static void decoder_close(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc);
static void convert_color_depth(uint8_t * img, uint32_t px_cnt);
static inline lv_color_t lv_color_make_rounding(uint8_t r, uint8_t g, uint8_t b);
/**********************
* STATIC VARIABLES
@@ -247,7 +246,7 @@ static void convert_color_depth(uint8_t * img, uint32_t px_cnt)
lv_color_t c;
uint32_t i;
for(i = 0; i < px_cnt; i++) {
c = lv_color_make_rounding(img_argb[i].ch.blue, img_argb[i].ch.green, img_argb[i].ch.red);
c = lv_color_make(img_argb[i].ch.blue, img_argb[i].ch.green, img_argb[i].ch.red);
img[i * 3 + 2] = img_argb[i].ch.alpha;
img[i * 3 + 1] = c.full >> 8;
img[i * 3 + 0] = c.full & 0xFF;
@@ -257,7 +256,7 @@ static void convert_color_depth(uint8_t * img, uint32_t px_cnt)
lv_color_t c;
uint32_t i;
for(i = 0; i < px_cnt; i++) {
c = lv_color_make_rounding(img_argb[i].ch.red, img_argb[i].ch.green, img_argb[i].ch.blue);
c = lv_color_make(img_argb[i].ch.red, img_argb[i].ch.green, img_argb[i].ch.blue);
img[i * 2 + 1] = img_argb[i].ch.alpha;
img[i * 2 + 0] = c.full;
}
@@ -273,15 +272,4 @@ static void convert_color_depth(uint8_t * img, uint32_t px_cnt)
#endif
}
static inline lv_color_t lv_color_make_rounding(uint8_t r, uint8_t g, uint8_t b)
{
#if LV_COLOR_DEPTH == 16
if(r <= 251) r += 4;
if(g <= 253) g += 2;
if(b <= 251) b += 4;
#endif
return lv_color_make(r, g, b);
}
#endif /*LV_USE_PNG*/

View File

@@ -348,7 +348,6 @@ lv_chart_series_t * lv_chart_add_series(lv_obj_t * obj, lv_color_t color, lv_cha
lv_chart_series_t * ser = _lv_ll_ins_head(&chart->series_ll);
LV_ASSERT_MALLOC(ser);
if(ser == NULL) return NULL;
lv_memset_00(ser, sizeof(lv_chart_series_t));
lv_coord_t def = LV_CHART_POINT_NONE;
@@ -366,6 +365,9 @@ lv_chart_series_t * lv_chart_add_series(lv_obj_t * obj, lv_color_t color, lv_cha
return NULL;
}
ser->start_point = 0;
ser->y_ext_buf_assigned = false;
ser->hidden = 0;
ser->x_axis_sec = axis & LV_CHART_AXIS_SECONDARY_X ? 1 : 0;
ser->y_axis_sec = axis & LV_CHART_AXIS_SECONDARY_Y ? 1 : 0;
@@ -679,7 +681,6 @@ static void lv_chart_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
ser = _lv_ll_get_head(&chart->series_ll);
if(!ser->y_ext_buf_assigned) lv_mem_free(ser->y_points);
if(!ser->x_ext_buf_assigned && ser->x_points) lv_mem_free(ser->x_points);
_lv_ll_remove(&chart->series_ll, ser);
lv_mem_free(ser);

View File

@@ -245,7 +245,7 @@ void lv_meter_set_indicator_value(lv_obj_t * obj, lv_meter_indicator_t * indic,
void lv_meter_set_indicator_start_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value);
/**
* Set the end value of the indicator.
* Set the start value of the indicator.
* @param obj pointer to a meter object
* @param indic pointer to an indicator
* @param value the new value

View File

@@ -70,7 +70,7 @@ typedef struct _lv_font_t {
/*Pointer to the font in a font pack (must have the same line height)*/
lv_coord_t line_height; /**< The real line height where any text fits*/
lv_coord_t base_line; /**< Base line measured from the bottom of the line_height*/
lv_coord_t base_line; /**< Base line measured from the top of the line_height*/
uint8_t subpx : 2; /**< An element of `lv_font_subpx_t`*/
int8_t underline_position; /**< Distance between the top of the underline and base line (< 0 means below the base line)*/

View File

@@ -26,7 +26,6 @@
#include "../draw/nxp/vglite/lv_draw_vglite.h"
#include "../draw/nxp/pxp/lv_draw_pxp.h"
#include "../draw/renesas/lv_gpu_d2_ra6m3.h"
#include "../draw/nema_gfx/lv_draw_nema_gfx.h"
#if LV_USE_THEME_DEFAULT
#include "../extra/themes/default/lv_theme_default.h"
@@ -125,10 +124,6 @@ void lv_disp_drv_init(lv_disp_drv_t * driver)
driver->draw_ctx_init = lv_draw_arm2d_ctx_init;
driver->draw_ctx_deinit = lv_draw_arm2d_ctx_init;
driver->draw_ctx_size = sizeof(lv_draw_arm2d_ctx_t);
#elif LV_USE_NEMA_GFX
driver->draw_ctx_init = lv_draw_nema_gfx_ctx_init;
driver->draw_ctx_deinit = lv_draw_nema_gfx_ctx_deinit;
driver->draw_ctx_size = sizeof(lv_draw_nema_gfx_ctx_t);
#else
driver->draw_ctx_init = lv_draw_sw_init_ctx;
driver->draw_ctx_deinit = lv_draw_sw_init_ctx;

View File

@@ -416,15 +416,6 @@
* GPU
*-----------*/
/*Use TSi's (aka Think Silicon) acceleration library NemaGFX */
#ifndef LV_USE_NEMA_GFX
#ifdef CONFIG_LV_USE_NEMA_GFX
#define LV_USE_NEMA_GFX CONFIG_LV_USE_NEMA_GFX
#else
#define LV_USE_NEMA_GFX 0
#endif
#endif
/*Use Arm's 2D acceleration library Arm-2D */
#ifndef LV_USE_GPU_ARM2D
#ifdef CONFIG_LV_USE_GPU_ARM2D

View File

@@ -550,11 +550,6 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e)
/*Set the new value*/
int16_t old_value = arc->value;
int16_t new_value = lv_map(angle, arc->bg_angle_start, bg_end, arc->min_value, arc->max_value);
if(arc->type == LV_ARC_MODE_REVERSE) {
new_value = arc->max_value - new_value + arc->min_value;
}
if(new_value != lv_arc_get_value(obj)) {
arc->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/
lv_arc_set_value(obj, new_value); /*set_value caches the last_angle for the next iteration*/

View File

@@ -246,7 +246,7 @@ void lv_canvas_draw_polygon(lv_obj_t * canvas, const lv_point_t points[], uint32
* @param r radius of the arc
* @param start_angle start angle in degrees
* @param end_angle end angle in degrees
* @param draw_dsc pointer to an initialized `lv_draw_arc_dsc_t` variable
* @param draw_dsc pointer to an initialized `lv_draw_line_dsc_t` variable
*/
void lv_canvas_draw_arc(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t r, int32_t start_angle,
int32_t end_angle, const lv_draw_arc_dsc_t * draw_dsc);

View File

@@ -1059,7 +1059,6 @@ static void lv_label_refr_text(lv_obj_t * obj)
if(anim_template) {
a.act_time = anim_template->act_time;
a.repeat_delay = anim_template->repeat_delay;
a.repeat_cnt = anim_template->repeat_cnt;
}
else if(act_time < a.time) {
a.act_time = act_time; /*To keep the old position when the label text is updated mid-scrolling*/
@@ -1087,7 +1086,6 @@ static void lv_label_refr_text(lv_obj_t * obj)
if(anim_template) {
a.act_time = anim_template->act_time;
a.repeat_delay = anim_template->repeat_delay;
a.repeat_cnt = anim_template->repeat_cnt;
}
else if(act_time < a.time) {
a.act_time = act_time; /*To keep the old position when the label text is updated mid-scrolling*/

View File

@@ -347,7 +347,7 @@ static void lv_roller_event(const lv_obj_class_t * class_p, lv_event_t * e)
lv_indev_get_vect(indev, &p);
if(p.y) {
lv_obj_t * label = get_label(obj);
lv_obj_set_y(label, lv_obj_get_y_aligned(label) + p.y);
lv_obj_set_y(label, lv_obj_get_y(label) + p.y);
roller->moved = 1;
}
}
@@ -476,31 +476,26 @@ static void draw_main(lv_event_t * e)
if(lv_label_get_recolor(label)) label_dsc.flag |= LV_TEXT_FLAG_RECOLOR;
/*Get the size of the "selected text"*/
lv_point_t label_sel_size;
lv_txt_get_size(&label_sel_size, lv_label_get_text(label), label_dsc.font, label_dsc.letter_space,
label_dsc.line_space, lv_obj_get_width(obj), LV_TEXT_FLAG_EXPAND);
lv_point_t res_p;
lv_txt_get_size(&res_p, lv_label_get_text(label), label_dsc.font, label_dsc.letter_space, label_dsc.line_space,
lv_obj_get_width(obj), LV_TEXT_FLAG_EXPAND);
/*Move the selected label proportionally with the background label*/
lv_coord_t roller_h = lv_obj_get_height(obj);
int32_t label_y_prop = label->coords.y1 - (roller_h / 2 +
obj->coords.y1); /*label offset from the middle line of the roller*/
label_y_prop = (label_y_prop * 16384) / lv_obj_get_height(
label); /*Proportional position from the middle line (upscaled by << 14)*/
/*Apply a correction with different line heights*/
const lv_font_t * normal_label_font = lv_obj_get_style_text_font(obj, LV_PART_MAIN);
/*label offset from the middle line of the roller*/
int32_t label_y_prop = (label->coords.y1 + normal_label_font->line_height / 2) - (roller_h / 2 + obj->coords.y1);
/*Proportional position from the middle line.
*Will be 0 for the first option, and 1 for the last option (upscaled by << 14)*/
lv_coord_t remain_h = lv_obj_get_height(label) - normal_label_font->line_height;
if(remain_h > 0) {
label_y_prop = (label_y_prop << 14) / remain_h;
}
/*We don't want the selected label start and end exactly where the normal label is as
*a larger font won't centered on selected area.*/
int32_t corr = label_dsc.font->line_height;
lv_coord_t corr = (label_dsc.font->line_height - normal_label_font->line_height) / 2;
/*Apply the proportional position to the selected text*/
res_p.y -= corr;
int32_t label_sel_y = roller_h / 2 + obj->coords.y1;
label_sel_y += ((label_sel_size.y - corr) * label_y_prop) >> 14;
label_sel_y -= corr / 2;
label_sel_y += (label_y_prop * res_p.y) >> 14;
label_sel_y -= corr;
lv_coord_t bwidth = lv_obj_get_style_border_width(obj, LV_PART_MAIN);
lv_coord_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
@@ -511,7 +506,7 @@ static void draw_main(lv_event_t * e)
label_sel_area.x1 = obj->coords.x1 + pleft + bwidth;
label_sel_area.y1 = label_sel_y;
label_sel_area.x2 = obj->coords.x2 - pright - bwidth;
label_sel_area.y2 = label_sel_area.y1 + label_sel_size.y;
label_sel_area.y2 = label_sel_area.y1 + res_p.y;
label_dsc.flag |= LV_TEXT_FLAG_EXPAND;
const lv_area_t * clip_area_ori = draw_ctx->clip_area;

View File

@@ -52,7 +52,7 @@ typedef struct {
#if LV_USE_USER_DATA
void * user_data; /**< Custom user data*/
#endif
char txt[1];
char txt[];
} lv_table_cell_t;
/*Data of table*/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -21,10 +21,6 @@ extern "C" {
*********************/
#define LV_USE_TINY_TTF 1
#define LV_FONT_MONTSERRAT_8 1
#define LV_FONT_MONTSERRAT_16 1
#define LV_FONT_MONTSERRAT_24 1
#define LV_FONT_MONTSERRAT_36 1
void lv_test_assert_fail(void);
#define LV_ASSERT_HANDLER lv_test_assert_fail();

View File

@@ -1,107 +0,0 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
/**
* see test_roller.c from v9.1 to borrow more test fixture components
*/
static lv_obj_t * active_screen = NULL;
static lv_obj_t * roller = NULL;
static lv_obj_t * roller_infinite = NULL;
void setUp(void)
{
active_screen = lv_scr_act();
roller = lv_roller_create(active_screen);
roller_infinite = lv_roller_create(active_screen);
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
void test_roller_appearance(void)
{
/* use a number, a symbol, a high letter, a low letter */
const char * opts =
"0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg\n0@Tg";
lv_obj_t * rollers[10] = {roller, roller_infinite};
uint32_t i = 2;
/* a normal and infinite roller with the same size font for the main and selected parts */
lv_obj_set_pos(roller, 20, 20);
lv_roller_set_options(roller, opts, LV_PART_MAIN);
lv_obj_set_pos(roller_infinite, 20, 200);
lv_roller_set_options(roller_infinite, opts, LV_ROLLER_MODE_INFINITE);
/* a normal and infinite roller with slightly different size fonts for the main and selected parts */
lv_obj_t * r = lv_roller_create(active_screen);
lv_obj_set_pos(r, 130, 20);
lv_roller_set_options(r, opts, LV_ROLLER_MODE_NORMAL);
lv_obj_set_style_text_font(r, &lv_font_montserrat_16, LV_PART_MAIN);
lv_obj_set_style_text_font(r, &lv_font_montserrat_24, LV_PART_SELECTED);
rollers[i++] = r;
r = lv_roller_create(active_screen);
lv_obj_set_pos(r, 130, 200);
lv_roller_set_options(r, opts, LV_ROLLER_MODE_INFINITE);
lv_obj_set_style_text_font(r, &lv_font_montserrat_16, LV_PART_MAIN);
lv_obj_set_style_text_font(r, &lv_font_montserrat_24, LV_PART_SELECTED);
rollers[i++] = r;
/* same as previous pair but the fonts are swapped for the main and selected parts */
r = lv_roller_create(active_screen);
lv_obj_set_pos(r, 270, 20);
lv_roller_set_options(r, opts, LV_ROLLER_MODE_NORMAL);
lv_obj_set_style_text_font(r, &lv_font_montserrat_24, LV_PART_MAIN);
lv_obj_set_style_text_font(r, &lv_font_montserrat_16, LV_PART_SELECTED);
rollers[i++] = r;
r = lv_roller_create(active_screen);
lv_obj_set_pos(r, 270, 200);
lv_roller_set_options(r, opts, LV_ROLLER_MODE_INFINITE);
lv_obj_set_style_text_font(r, &lv_font_montserrat_24, LV_PART_MAIN);
lv_obj_set_style_text_font(r, &lv_font_montserrat_16, LV_PART_SELECTED);
rollers[i++] = r;
/* a normal and infinite roller with extremely different size fonts for the main and selected parts */
r = lv_roller_create(active_screen);
lv_obj_set_pos(r, 410, 20);
lv_roller_set_options(r, opts, LV_ROLLER_MODE_NORMAL);
lv_obj_set_style_text_font(r, &lv_font_montserrat_8, LV_PART_MAIN);
lv_obj_set_style_text_font(r, &lv_font_montserrat_36, LV_PART_SELECTED);
rollers[i++] = r;
r = lv_roller_create(active_screen);
lv_obj_set_pos(r, 410, 200);
lv_roller_set_options(r, opts, LV_ROLLER_MODE_INFINITE);
lv_obj_set_style_text_font(r, &lv_font_montserrat_8, LV_PART_MAIN);
lv_obj_set_style_text_font(r, &lv_font_montserrat_36, LV_PART_SELECTED);
rollers[i++] = r;
/* same as previous pair but the fonts are swapped for the main and selected parts */
r = lv_roller_create(active_screen);
lv_obj_set_pos(r, 580, 20);
lv_roller_set_options(r, opts, LV_ROLLER_MODE_NORMAL);
lv_obj_set_style_text_font(r, &lv_font_montserrat_36, LV_PART_MAIN);
lv_obj_set_style_text_font(r, &lv_font_montserrat_8, LV_PART_SELECTED);
rollers[i++] = r;
r = lv_roller_create(active_screen);
lv_obj_set_pos(r, 580, 200);
lv_roller_set_options(r, opts, LV_ROLLER_MODE_INFINITE);
lv_obj_set_style_text_font(r, &lv_font_montserrat_36, LV_PART_MAIN);
lv_obj_set_style_text_font(r, &lv_font_montserrat_8, LV_PART_SELECTED);
rollers[i++] = r;
TEST_ASSERT_EQUAL_SCREENSHOT("roller_1.png");
/* test that the selected label stays in sync with the main label for scrolling */
for(i = 0; i < 10; i++) {
lv_roller_set_selected(rollers[i], lv_roller_get_option_cnt(rollers[i]) - 1, LV_ANIM_OFF);
}
TEST_ASSERT_EQUAL_SCREENSHOT("roller_2.png");
}
#endif

View File

@@ -2,7 +2,6 @@
#include "../lvgl.h"
#include "unity/unity.h"
#include "lv_test_indev.h"
void test_screen_load_no_crash(void)
{
@@ -17,111 +16,4 @@ void test_screen_load_no_crash(void)
lv_scr_load_anim(screen_with_anim_2, LV_SCR_LOAD_ANIM_OVER_RIGHT, 1000, 500, false);
}
void test_screen_load_with_delete_no_crash(void)
{
/*load new screen should not crash*/
lv_obj_t * screen = lv_obj_create(NULL);
lv_scr_load(screen);
/*Consecutively loading multiple screens (while deleting one) with transition animations should not crash*/
lv_obj_t * screen_with_anim_1 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_2 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_3 = lv_obj_create(NULL);
lv_scr_load_anim(screen_with_anim_1, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, false);
lv_scr_load_anim(screen_with_anim_2, LV_SCR_LOAD_ANIM_OVER_RIGHT, 1000, 0, true);
/*Wait to trigger the animation start callbacks*/
lv_test_indev_wait(100);
lv_scr_load_anim(screen_with_anim_3, LV_SCR_LOAD_ANIM_OVER_LEFT, 200, 0, true);
/*The active screen should be immediately replaced*/
TEST_ASSERT_EQUAL(lv_scr_act(), screen_with_anim_2);
lv_test_indev_wait(400);
/*Check for the screens status after the transition*/
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_1), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_2), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_3), true);
}
void test_screen_load_with_delete_no_crash2(void)
{
/*load new screen should not crash*/
lv_obj_t * screen = lv_obj_create(NULL);
lv_scr_load(screen);
/*Consecutively loading multiple screens (while deleting one) with transition animations should not crash*/
lv_obj_t * screen_with_anim_1 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_2 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_3 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_4 = lv_obj_create(NULL);
lv_scr_load_anim(screen_with_anim_1, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, false);
lv_scr_load_anim(screen_with_anim_2, LV_SCR_LOAD_ANIM_OVER_RIGHT, 1000, 0, true);
lv_scr_load_anim(screen_with_anim_3, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, true);
/*Wait to trigger the animation start callbacks*/
lv_test_indev_wait(100);
lv_scr_load_anim(screen_with_anim_4, LV_SCR_LOAD_ANIM_OVER_LEFT, 200, 0, true);
/*The active screen should be immediately replaced*/
TEST_ASSERT_EQUAL(lv_scr_act(), screen_with_anim_3);
lv_test_indev_wait(400);
/*Check for the screens status after the transition*/
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_1), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_2), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_3), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_4), true);
}
static bool screen_1_unloaded_called = false;
static void screen_with_anim_1_unloaded_cb(lv_event_t * e)
{
LV_UNUSED(e);
screen_1_unloaded_called = true;
}
void test_screen_load_with_delete_event(void)
{
/*load new screen should not crash*/
lv_obj_t * screen = lv_obj_create(NULL);
lv_scr_load(screen);
/*Consecutively loading multiple screens (while deleting one) with transition animations should not crash*/
lv_obj_t * screen_with_anim_1 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_2 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_3 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_4 = lv_obj_create(NULL);
lv_scr_load_anim(screen_with_anim_1, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, false);
lv_obj_add_event_cb(screen_with_anim_1, screen_with_anim_1_unloaded_cb, LV_EVENT_SCREEN_UNLOADED, NULL);
lv_scr_load_anim(screen_with_anim_2, LV_SCR_LOAD_ANIM_OVER_RIGHT, 1000, 0, true);
lv_scr_load_anim(screen_with_anim_3, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, true);
/*Wait to trigger the animation start callbacks*/
lv_test_indev_wait(100);
TEST_ASSERT_EQUAL(screen_1_unloaded_called, true);
lv_scr_load_anim(screen_with_anim_4, LV_SCR_LOAD_ANIM_OVER_LEFT, 200, 0, true);
/*The active screen should be immediately replaced*/
TEST_ASSERT_EQUAL(lv_scr_act(), screen_with_anim_3);
lv_test_indev_wait(400);
/*Check for the screens status after the transition*/
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_1), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_2), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_3), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_4), true);
}
#endif