This commit is contained in:
Gabor Kiss-Vamosi
2021-07-19 15:35:47 +02:00
32 changed files with 1359 additions and 152 deletions

View File

@@ -34,6 +34,7 @@ PDF version: :download:`LVGL.pdf <LVGL.pdf>`
overview/index
widgets/index
layouts/index
others/index
CONTRIBUTING
CHANGELOG
ROADMAP

BIN
docs/misc/anim-timeline.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

16
docs/others/index.md Normal file
View File

@@ -0,0 +1,16 @@
```eval_rst
.. include:: /header.rst
:github_url: |github_link_base|/others/index.md
```
# Others
```eval_rst
.. toctree::
:maxdepth: 1
snapshot
```

67
docs/others/snapshot.md Normal file
View File

@@ -0,0 +1,67 @@
```eval_rst
.. include:: /header.rst
:github_url: |github_link_base|/others/snapshot.md
```
# Snapshot
Snapshot provides APIs to take snapshot image for LVGL object together with its children. The image will look exactly like the object.
## Usage
Simply call API `lv_snapshot_take` to generate the image descriptor which can be set as image object src using `lv_img_set_src`.
Note, only below color formats are supported for now:
- LV_IMG_CF_TRUE_COLOR_ALPHA
- LV_IMG_CF_ALPHA_1BIT
- LV_IMG_CF_ALPHA_2BIT
- LV_IMG_CF_ALPHA_4BIT
- LV_IMG_CF_ALPHA_8BIT
### Free the Image
The memory `lv_snapshot_take` uses are dynamically allocated using `lv_mem_alloc`. Use API `lv_snapshot_free` to free the memory it takes. This will firstly free memory the image data takes, then the image descriptor.
Take caution to free the snapshot but not delete the image object. Before free the memory, be sure to firstly unlink it from image object, using `lv_img_set_src(NULL)` and `lv_img_cache_invalidate_src(src)`.
Below code snippet explains usage of this API.
```c
void update_snapshot(lv_obj_t * obj, lv_obj_t * img_snapshot)
{
lv_img_dsc_t* snapshot = (void*)lv_img_get_src(img_snapshot);
if(snapshot) {
lv_snapshot_free(snapshot);
}
snapshot = lv_snapshot_take(obj, LV_IMG_CF_TRUE_COLOR_ALPHA);
lv_img_set_src(img_snapshot, snapshot);
}
```
### Use Existing Buffer
If the snapshot needs update now and then, or simply caller provides memory, use API `lv_res_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_img_cf_t cf, lv_img_dsc_t * dsc, void * buf, uint32_t buff_size);` for this case. It's caller's responsibility to alloc/free the memory.
If snapshot is generated successfully, the image descriptor is updated and image data will be stored to provided `buf`.
Note that snapshot may fail if provided buffer is not enough, which may happen when object size changes. It's recommended to use API `lv_snapshot_buf_size_needed` to check the needed buffer size in byte firstly and resize the buffer accordingly.
## Example
```eval_rst
.. include:: ../../examples/others/snapshot/index.rst
```
## API
```eval_rst
.. doxygenfile:: lv_snapshot.h
:project: lvgl
```

View File

@@ -104,6 +104,28 @@ The speed is interpreted in _unit/sec_ dimension. For example, `lv_anim_speed_t
You can delete an animation with `lv_anim_del(var, func)` if you provide the animated variable and its animator function.
## Timeline
Timeline is a collection of multiple Animations, which makes it easy to create complex composite animations.
Firstly, create the animation element, but dont call `lv_anim_start()`.
Secondly, create an animation timeline object, by calling `lv_anim_timeline_create()`.
Thirdly, add animation elements to the animation timeline, by calling `lv_anim_timeline_add(at, start_time, &a)`. `start_time` is the start time of the animation on the timeline. Note that `start_time` will override the value of `delay`.
Finally, call `lv_anim_timeline_start(at)` to start the animation timeline.
It supports forward and backward playback of the entire animation group, using `lv_anim_timeline_set_reverse(at, reverse)`.
Call the `lv_anim_timeline_set_progress(at, progress)` function to set the state of the object corresponding to the progress of the timeline.
Call the `lv_anim_timeline_get_playtime(at)` function to get the total duration of the entire animation timeline.
Call the `lv_anim_timeline_get_reverse(at)` function to get whether to reverse the animation timeline.
Call the `lv_anim_timeline_del(at)` function to delete the animation timeline.
![](/misc/anim-timeline.png "timeline diagram")
## Examples

View File

@@ -218,3 +218,5 @@ In both cases ORed state values can be used as well. E.g. `lv_obj_add_state(obj,
To learn more about the states read the related section of the [Style overview](/overview/style).
## Snapshot
A snapshot image could be generated for object together with its children. Check details in [Snapshot](/others/snapshot).

View File

@@ -123,7 +123,7 @@ indev_drv.read_cb = encoder_with_keys_read;
...
bool encoder_with_keys_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
void encoder_with_keys_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
data->key = last_key(); /*Get the last pressed or released key*/
/* use LV_KEY_ENTER for encoder press */
if(key_pressed()) data->state = LV_INDEV_STATE_PRESSED;
@@ -132,8 +132,6 @@ bool encoder_with_keys_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
/* Optionally you can also use enc_diff, if you have encoder*/
data->enc_diff = enc_get_new_moves();
}
return false; /*No buffering now so no more data read*/
}
```

View File

@@ -19,6 +19,18 @@ The spangroup object uses span to describe text and text style. so, first we nee
If spangroup object `mode != LV_SPAN_MODE_FIXED` you must call `lv_spangroup_refr_mode()` after you have modified `span` style(eg:set text, changed the font size, del span).
### Retreiving a span child
Spangroups store their children differently from normal objects, so normal functions for getting children won't work.
`lv_spangroup_get_child(spangroup, id)` will return a pointer to the child span at index `id`. In addition, `id` can be negative to index from the end of the spangroup where `-1` is the youngest child, `-2` is second youngest, etc.
e.g. `lv_span_t* span = lv_spangroup_get_child(spangroup, 0)` will return the first child of the spangroup. `lv_span_t* span = lv_spangroup_get_child(spangroup, -1)` will return the last (or most recent) child.
### Child Count
Use the function `lv_spangroup_get_child_cnt(spangroup)` to get back the number of spans the group is maintaining.
e.g. `uint32_t size = lv_spangroup_get_child_cnt(spangroup)`
### Text align
like label object, the spangroup can be set to one the following modes:
- `LV_TEXT_ALIGN_LEFT` Align text to left.

View File

@@ -10,4 +10,8 @@ Playback animation
.. lv_example:: anim/lv_example_anim_2
:language: c
Animation timeline
"""""""""""""""""""
.. lv_example:: anim/lv_example_anim_timeline_1.c
:language: c

View File

@@ -27,6 +27,7 @@ extern "C" {
**********************/
void lv_example_anim_1(void);
void lv_example_anim_2(void);
void lv_example_anim_timeline_1(void);
/**********************
* MACROS

View File

@@ -0,0 +1,170 @@
#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES
static lv_anim_timeline_t * anim_timeline = NULL;
static lv_obj_t * obj1 = NULL;
static lv_obj_t * obj2 = NULL;
static lv_obj_t * obj3 = NULL;
static const lv_coord_t obj_width = 150;
static const lv_coord_t obj_height = 200;
static void set_width(void * var, int32_t v)
{
lv_obj_set_width((lv_obj_t *)var, v);
}
static void set_height(void * var, int32_t v)
{
lv_obj_set_height((lv_obj_t *)var, v);
}
static void anim_timeline_create(void)
{
/* obj1 */
lv_anim_t a1;
lv_anim_init(&a1);
lv_anim_set_var(&a1, obj1);
lv_anim_set_values(&a1, 0, obj_width);
lv_anim_set_early_apply(&a1, false);
lv_anim_set_exec_cb(&a1, (lv_anim_exec_xcb_t)set_width);
lv_anim_set_path_cb(&a1, lv_anim_path_overshoot);
lv_anim_set_time(&a1, 300);
lv_anim_t a2;
lv_anim_init(&a2);
lv_anim_set_var(&a2, obj1);
lv_anim_set_values(&a2, 0, obj_height);
lv_anim_set_early_apply(&a2, false);
lv_anim_set_exec_cb(&a2, (lv_anim_exec_xcb_t)set_height);
lv_anim_set_path_cb(&a2, lv_anim_path_ease_out);
lv_anim_set_time(&a2, 300);
/* obj2 */
lv_anim_t a3;
lv_anim_init(&a3);
lv_anim_set_var(&a3, obj2);
lv_anim_set_values(&a3, 0, obj_width);
lv_anim_set_early_apply(&a3, false);
lv_anim_set_exec_cb(&a3, (lv_anim_exec_xcb_t)set_width);
lv_anim_set_path_cb(&a3, lv_anim_path_overshoot);
lv_anim_set_time(&a3, 300);
lv_anim_t a4;
lv_anim_init(&a4);
lv_anim_set_var(&a4, obj2);
lv_anim_set_values(&a4, 0, obj_height);
lv_anim_set_early_apply(&a4, false);
lv_anim_set_exec_cb(&a4, (lv_anim_exec_xcb_t)set_height);
lv_anim_set_path_cb(&a4, lv_anim_path_ease_out);
lv_anim_set_time(&a4, 300);
/* obj3 */
lv_anim_t a5;
lv_anim_init(&a5);
lv_anim_set_var(&a5, obj3);
lv_anim_set_values(&a5, 0, obj_width);
lv_anim_set_early_apply(&a5, false);
lv_anim_set_exec_cb(&a5, (lv_anim_exec_xcb_t)set_width);
lv_anim_set_path_cb(&a5, lv_anim_path_overshoot);
lv_anim_set_time(&a5, 300);
lv_anim_t a6;
lv_anim_init(&a6);
lv_anim_set_var(&a6, obj3);
lv_anim_set_values(&a6, 0, obj_height);
lv_anim_set_early_apply(&a6, false);
lv_anim_set_exec_cb(&a6, (lv_anim_exec_xcb_t)set_height);
lv_anim_set_path_cb(&a6, lv_anim_path_ease_out);
lv_anim_set_time(&a6, 300);
/* Create anim timeline */
anim_timeline = lv_anim_timeline_create();
lv_anim_timeline_add(anim_timeline, 0, &a1);
lv_anim_timeline_add(anim_timeline, 0, &a2);
lv_anim_timeline_add(anim_timeline, 200, &a3);
lv_anim_timeline_add(anim_timeline, 200, &a4);
lv_anim_timeline_add(anim_timeline, 400, &a5);
lv_anim_timeline_add(anim_timeline, 400, &a6);
}
static void btn_run_event_handler(lv_event_t * e)
{
lv_obj_t * btn = lv_event_get_target(e);
if (!anim_timeline) {
anim_timeline_create();
}
bool reverse = lv_obj_has_state(btn, LV_STATE_CHECKED);
lv_anim_timeline_set_reverse(anim_timeline, reverse);
lv_anim_timeline_start(anim_timeline);
}
static void btn_del_event_handler(lv_event_t * e)
{
LV_UNUSED(e);
if (anim_timeline) {
lv_anim_timeline_del(anim_timeline);
anim_timeline = NULL;
}
}
static void slider_prg_event_handler(lv_event_t * e)
{
lv_obj_t * slider = lv_event_get_target(e);
if (!anim_timeline) {
anim_timeline_create();
}
int32_t progress = lv_slider_get_value(slider);
lv_anim_timeline_set_progress(anim_timeline, progress);
}
/**
* Create an animation timeline
*/
void lv_example_anim_timeline_1(void)
{
lv_obj_t * par = lv_scr_act();
lv_obj_set_flex_flow(par, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(par, LV_FLEX_ALIGN_SPACE_AROUND, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t * btn_run = lv_btn_create(par);
lv_obj_add_event_cb(btn_run, btn_run_event_handler, LV_EVENT_VALUE_CHANGED, NULL);
lv_obj_add_flag(btn_run, LV_OBJ_FLAG_IGNORE_LAYOUT);
lv_obj_add_flag(btn_run, LV_OBJ_FLAG_CHECKABLE);
lv_obj_align(btn_run, LV_ALIGN_TOP_MID, -50, 20);
lv_obj_t * label_run = lv_label_create(btn_run);
lv_label_set_text(label_run, "Run");
lv_obj_center(label_run);
lv_obj_t * btn_del = lv_btn_create(par);
lv_obj_add_event_cb(btn_del, btn_del_event_handler, LV_EVENT_CLICKED, NULL);
lv_obj_add_flag(btn_del, LV_OBJ_FLAG_IGNORE_LAYOUT);
lv_obj_align(btn_del, LV_ALIGN_TOP_MID, 50, 20);
lv_obj_t * label_del = lv_label_create(btn_del);
lv_label_set_text(label_del, "Stop");
lv_obj_center(label_del);
lv_obj_t * slider_prg = lv_slider_create(par);
lv_obj_add_event_cb(slider_prg, slider_prg_event_handler, LV_EVENT_VALUE_CHANGED, NULL);
lv_obj_add_flag(slider_prg, LV_OBJ_FLAG_IGNORE_LAYOUT);
lv_obj_align(slider_prg, LV_ALIGN_BOTTOM_MID, 0, -20);
lv_slider_set_range(slider_prg, 0, 65535);
obj1 = lv_obj_create(par);
lv_obj_set_size(obj1, obj_width, obj_height);
obj2 = lv_obj_create(par);
lv_obj_set_size(obj2, obj_width, obj_height);
obj3 = lv_obj_create(par);
lv_obj_set_size(obj3, obj_width, obj_height);
}
#endif

View File

@@ -23,6 +23,7 @@ extern "C" {
#include "anim/lv_example_anim.h"
#include "event/lv_example_event.h"
#include "styles/lv_example_style.h"
#include "others/lv_example_others.h"
/*********************
* DEFINES

View File

@@ -0,0 +1,37 @@
/**
* @file lv_example_others.h
*
*/
#ifndef LV_EXAMPLE_OTHERS_H
#define LV_EXAMPLE_OTHERS_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "snapshot/lv_example_snapshot.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_EX_OTHERS_H*/

View File

@@ -0,0 +1,8 @@
Simple snapshot example
"""""""""""""""""""
.. lv_example:: others/snapshot/lv_example_snapshot_1
:language: c

View File

@@ -0,0 +1,38 @@
/**
* @file lv_example_snapshot.h
*
*/
#ifndef LV_EX_SNAPSHOT_H
#define LV_EX_SNAPSHOT_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_example_snapshot_1(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_EX_GET_STARTED_H*/

View File

@@ -0,0 +1,57 @@
#include "../../lv_examples.h"
#if LV_USE_SNAPSHOT && LV_BUILD_EXAMPLES
static void event_cb(lv_event_t* e)
{
lv_obj_t * snapshot_obj = lv_event_get_user_data(e);
lv_obj_t * img = lv_event_get_target(e);
if(snapshot_obj) {
lv_img_dsc_t* snapshot = (void*)lv_img_get_src(snapshot_obj);
if(snapshot){
lv_snapshot_free(snapshot);
}
/*Update the snapshot, we know parent of object is the container.*/
snapshot = lv_snapshot_take(img->parent, LV_IMG_CF_TRUE_COLOR_ALPHA);
if(snapshot == NULL)
return;
lv_img_set_src(snapshot_obj, snapshot);
}
}
void lv_example_snapshot_1(void)
{
LV_IMG_DECLARE(img_star);
lv_obj_t * root = lv_scr_act();
lv_obj_set_style_bg_color(root, lv_palette_main(LV_PALETTE_LIGHT_BLUE), 0);
/*Create an image object to show snapshot*/
lv_obj_t * snapshot_obj = lv_img_create(root);
lv_obj_set_style_bg_color(snapshot_obj, lv_palette_main(LV_PALETTE_PURPLE), 0);
lv_obj_set_style_bg_opa(snapshot_obj, LV_OPA_100, 0);
lv_img_set_zoom(snapshot_obj, 128);
/*Create the container and its children*/
lv_obj_t * container = lv_obj_create(root);
lv_obj_align(container, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_size(container, 180, 180);
lv_obj_set_flex_flow(container, LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(container, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_radius(container, 50, 0);
lv_obj_t * img;
int i;
for(i = 0; i < 4; i++) {
img = lv_img_create(container);
lv_img_set_src(img, &img_star);
lv_obj_set_style_bg_color(img, lv_color_black(), 0);
lv_obj_set_style_bg_opa(img, LV_OPA_COVER, 0);
lv_obj_set_style_transform_zoom(img, 400, LV_STATE_PRESSED);
lv_obj_add_flag(img, LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_event_cb(img, event_cb, LV_EVENT_PRESSED, snapshot_obj);
lv_obj_add_event_cb(img, event_cb, LV_EVENT_RELEASED, snapshot_obj);
}
}
#endif

View File

@@ -0,0 +1,70 @@
import lvgl as lv
from imagetools import get_png_info, open_png
# Register PNG image decoder
decoder = lv.img.decoder_create()
decoder.info_cb = get_png_info
decoder.open_cb = open_png
# Measure memory usage
gc.enable()
gc.collect()
mem_free = gc.mem_free()
label = lv.label(lv.scr_act())
label.align(lv.ALIGN.BOTTOM_MID, 0, -10)
label.set_text(" memory free:" + str(mem_free/1024) + " kB")
# Create an image from the png file
try:
with open('../../assets/img_star.png','rb') as f:
png_data = f.read()
except:
print("Could not find img_star.png")
sys.exit()
img_star = lv.img_dsc_t({
'data_size': len(png_data),
'data': png_data
})
def event_cb(e, snapshot_obj):
img = e.get_target()
if snapshot_obj:
# no need to free the old source for snapshot_obj, gc will free it for us.
# take a new snapshot, overwrite the old one
dsc = lv.snapshot_take(img.get_parent(), lv.img.CF.TRUE_COLOR_ALPHA)
snapshot_obj.set_src(dsc)
gc.collect()
mem_used = mem_free - gc.mem_free()
label.set_text("memory used:" + str(mem_used/1024) + " kB")
root = lv.scr_act()
root.set_style_bg_color(lv.palette_main(lv.PALETTE.LIGHT_BLUE), 0)
# Create an image object to show snapshot
snapshot_obj = lv.img(root)
snapshot_obj.set_style_bg_color(lv.palette_main(lv.PALETTE.PURPLE), 0)
snapshot_obj.set_style_bg_opa(lv.OPA.COVER, 0)
snapshot_obj.set_zoom(128)
# Create the container and its children
container = lv.obj(root)
container.align(lv.ALIGN.CENTER, 0, 0)
container.set_size(180, 180)
container.set_flex_flow(lv.FLEX_FLOW.ROW_WRAP)
container.set_flex_align(lv.FLEX_ALIGN.SPACE_EVENLY, lv.FLEX_ALIGN.CENTER, lv.FLEX_ALIGN.CENTER)
container.set_style_radius(50, 0)
for i in range(4):
img = lv.img(container)
img.set_src(img_star)
img.set_style_bg_color(lv.palette_main(lv.PALETTE.GREY), 0)
img.set_style_bg_opa(lv.OPA.COVER, 0)
img.set_style_transform_zoom(400, lv.STATE.PRESSED)
img.add_flag(img.FLAG.CLICKABLE)
img.add_event_cb(lambda e: event_cb(e, snapshot_obj), lv.EVENT.PRESSED, None)
img.add_event_cb(lambda e: event_cb(e, snapshot_obj), lv.EVENT.RELEASED, None)

View File

@@ -214,6 +214,9 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
# define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/
#endif /*LV_ENABLE_GC*/
/*1: Enable API to take snapshot for object*/
#define LV_USE_SNAPSHOT 1
/*=====================
* COMPILER SETTINGS
*====================*/

2
lvgl.h
View File

@@ -26,6 +26,7 @@ extern "C" {
#include "src/misc/lv_timer.h"
#include "src/misc/lv_math.h"
#include "src/misc/lv_async.h"
#include "src/misc/lv_anim_timeline.h"
#include "src/hal/lv_hal.h"
@@ -69,6 +70,7 @@ extern "C" {
#include "src/extra/widgets/lv_widgets.h"
#include "src/extra/layouts/lv_layouts.h"
#include "src/extra/themes/lv_themes.h"
#include "src/extra/others/lv_others.h"
/*********************
* DEFINES

View File

@@ -0,0 +1,38 @@
/**
* @file lv_others.h
*
*/
#ifndef LV_OTHERS_H
#define LV_OTHERS_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "snapshot/lv_snapshot.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OTHERS_H*/

View File

@@ -0,0 +1,213 @@
/**
* @file lv_snapshot.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_snapshot.h"
#if LV_USE_SNAPSHOT
#include <stdbool.h>
#include "../../../core/lv_disp.h"
#include "../../../core/lv_refr.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/** Get the buffer needed for object snapshot image.
*
* @param obj The object to generate snapshot.
* @param cf color format for generated image.
*
* @return the buffer size needed in bytes
*/
uint32_t lv_snapshot_buf_size_needed(lv_obj_t * obj, lv_img_cf_t cf)
{
switch(cf) {
case LV_IMG_CF_TRUE_COLOR_ALPHA:
case LV_IMG_CF_ALPHA_1BIT:
case LV_IMG_CF_ALPHA_2BIT:
case LV_IMG_CF_ALPHA_4BIT:
case LV_IMG_CF_ALPHA_8BIT:
break;
default:
return 0;
}
lv_obj_update_layout(obj);
/*Width and height determine snapshot image size.*/
lv_coord_t w = lv_obj_get_width(obj);
lv_coord_t h = lv_obj_get_height(obj);
uint8_t px_size = lv_img_cf_get_px_size(cf);
return w * h * ((px_size + 7) >> 3);
}
/** Take snapshot for object with its children, save image info to provided buffer.
*
* @param obj The object to generate snapshot.
* @param cf color format for generated image.
* @param dsc image descriptor to store the image result.
* @param buf the buffer to store image data.
* @param buff_size provided buffer size in bytes.
*
* @return LV_RES_OK on success, LV_RES_INV on error.
*/
lv_res_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_img_cf_t cf, lv_img_dsc_t * dsc, void * buf, uint32_t buff_size)
{
LV_ASSERT(dsc);
LV_ASSERT(buf);
switch(cf) {
case LV_IMG_CF_TRUE_COLOR_ALPHA:
case LV_IMG_CF_ALPHA_1BIT:
case LV_IMG_CF_ALPHA_2BIT:
case LV_IMG_CF_ALPHA_4BIT:
case LV_IMG_CF_ALPHA_8BIT:
break;
default:
return LV_RES_INV;
}
if(lv_snapshot_buf_size_needed(obj, cf) > buff_size)
return LV_RES_INV;
/*Width and height determine snapshot image size.*/
lv_coord_t w = lv_obj_get_width(obj);
lv_coord_t h = lv_obj_get_height(obj);
/*Backup obj original info.*/
lv_disp_t * disp_old = lv_obj_get_disp(obj);
lv_obj_t * parent_old = lv_obj_get_parent(obj);
lv_memset(buf, 0x00, buff_size);
lv_memset_00(dsc, sizeof(lv_img_dsc_t));
/*We are safe to use stack for below variables since disp will be
* unregistered when function returns. */
lv_disp_t * disp;
lv_disp_drv_t driver;
lv_disp_draw_buf_t draw_buf;
lv_disp_draw_buf_init(&draw_buf, buf, NULL, w * h);
lv_disp_drv_init(&driver);
driver.draw_buf = &draw_buf;
driver.hor_res = lv_disp_get_hor_res(disp_old);
driver.ver_res = lv_disp_get_ver_res(disp_old);
lv_disp_drv_use_generic_set_px_cb(&driver, cf);
disp = lv_disp_drv_register(&driver);
if(disp == NULL) {
return LV_RES_INV;
}
/*Make background transparent */
lv_disp_set_bg_opa(disp, LV_OPA_TRANSP);
/*Move obj to newly created disp and refresh it. */
lv_obj_t * screen = lv_disp_get_scr_act(disp);
lv_obj_remove_style_all(screen);
lv_obj_allocate_spec_attr(screen);
screen->spec_attr->child_cnt = 1;
screen->spec_attr->children = &obj;
obj->parent = screen;
disp->inv_p = 0;
lv_obj_invalidate(obj);
/*Don't call lv_refr_now to avoid animation disruption */
_lv_disp_refr_timer(disp->refr_timer);
/*Restore obj original parameters and clean up*/
obj->parent = parent_old;
screen->spec_attr->child_cnt = 0;
screen->spec_attr->children = NULL;
lv_disp_remove(disp);
dsc->data = buf;
dsc->header.w = w;
dsc->header.h = h;
dsc->header.cf = cf;
return LV_RES_OK;
}
/** Take snapshot for object with its children, alloc the memory needed.
*
* @param obj The object to generate snapshot.
* @param cf color format for generated image.
*
* @return a pointer to a image descriptor, or NULL if failed.
*/
lv_img_dsc_t * lv_snapshot_take(lv_obj_t * obj, lv_img_cf_t cf)
{
uint32_t buff_size = lv_snapshot_buf_size_needed(obj, cf);
void * buf = lv_mem_alloc(buff_size);
if(buf == NULL) {
return NULL;
}
lv_img_dsc_t * dsc = lv_mem_alloc(sizeof(lv_img_dsc_t));
if(dsc == NULL) {
lv_mem_free(buf);
return NULL;
}
if(lv_snapshot_take_to_buf(obj, cf, dsc, buf, buff_size) == LV_RES_INV) {
lv_mem_free(buf);
lv_mem_free(dsc);
return NULL;
}
return dsc;
}
/** Free the snapshot image returned by @ref lv_snapshot_take
*
* It will firstly free the data image takes, then the image descriptor.
*
* @param dsc The image descriptor generated by lv_snapshot_take.
*
*/
void lv_snapshot_free(lv_img_dsc_t * dsc)
{
if(!dsc)
return;
if(dsc->data)
lv_mem_free((void *)dsc->data);
lv_mem_free(dsc);
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_SNAPSHOT*/

View File

@@ -0,0 +1,84 @@
/**
* @file lv_snapshot.h
*
*/
#ifndef LV_SNAPSHOT_H
#define LV_SNAPSHOT_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <stdint.h>
#include <stddef.h>
#include "../../../lv_conf_internal.h"
#include "../../../core/lv_obj.h"
/*********************
* DEFINES
*********************/
#if LV_USE_SNAPSHOT
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/** Take snapshot for object with its children.
*
* @param obj The object to generate snapshot.
* @param cf color format for generated image.
*
* @return a pointer to a image descriptor, or NULL if failed.
*/
lv_img_dsc_t * lv_snapshot_take(lv_obj_t * obj, lv_img_cf_t cf);
/** Free the snapshot image returned by @ref lv_snapshot_take
*
* It will firstly free the data image takes, then the image descriptor.
*
* @param dsc The image descriptor generated by lv_snapshot_take.
*
*/
void lv_snapshot_free(lv_img_dsc_t * dsc);
/** Get the buffer needed for object snapshot image.
*
* @param obj The object to generate snapshot.
* @param cf color format for generated image.
*
* @return the buffer size needed in bytes
*/
uint32_t lv_snapshot_buf_size_needed(lv_obj_t * obj, lv_img_cf_t cf);
/** Take snapshot for object with its children, save image info to provided buffer.
*
* @param obj The object to generate snapshot.
* @param cf color format for generated image.
* @param dsc image descriptor to store the image result.
* @param buff the buffer to store image data.
* @param buff_size provided buffer size in bytes.
*
* @return LV_RES_OK on success, LV_RES_INV on error.
*/
lv_res_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_img_cf_t cf, lv_img_dsc_t * dsc, void * buf, uint32_t buff_size);
/**********************
* MACROS
**********************/
#endif /*LV_USE_SNAPSHOT*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif

View File

@@ -254,6 +254,71 @@ void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode)
* Getter functions
*====================*/
/**
* Get a spangroup child by its index.
*
* @param obj The spangroup object
* @param id the index of the child.
* 0: the oldest (firstly created) child
* 1: the second oldest
* child count-1: the youngest
* -1: the youngest
* -2: the second youngest
* @return The child span at index `id`, or NULL if the ID does not exist
*/
lv_span_t * lv_spangroup_get_child(const lv_obj_t * obj, int32_t id)
{
if(obj == NULL) {
return NULL;
}
lv_spangroup_t * spans = (lv_spangroup_t *)obj;
lv_ll_t * linked_list = &spans->child_ll;
bool traverse_forwards = (id >= 0);
int32_t cur_idx = 0;
lv_ll_node_t * cur_node = linked_list->head;
/*If using a negative index, start from the tail and use cur -1 to indicate the end*/
if(!traverse_forwards) {
cur_idx = -1;
cur_node = linked_list->tail;
}
while(cur_node != NULL) {
if(cur_idx == id) {
return (lv_span_t *) cur_node;
}
if(traverse_forwards) {
cur_node = (lv_ll_node_t *) _lv_ll_get_next(linked_list, cur_node);
cur_idx++;
}
else {
cur_node = (lv_ll_node_t *) _lv_ll_get_prev(linked_list, cur_node);
cur_idx--;
}
}
return NULL;
}
/**
*
* @param obj The spangroup object to get the child count of.
* @return The span count of the spangroup.
*/
uint32_t lv_spangroup_get_child_cnt(const lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
if(obj == NULL) {
return 0;
}
lv_spangroup_t * spans = (lv_spangroup_t *)obj;
return _lv_ll_get_len(&(spans->child_ll));
}
/**
* get the align of the spangroup.
* @param obj pointer to a spangroup object.

View File

@@ -137,6 +137,27 @@ void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode);
* Getter functions
*====================*/
/**
* Get a spangroup child by its index.
*
* @param obj The spangroup object
* @param id the index of the child.
* 0: the oldest (firstly created) child
* 1: the second oldest
* child count-1: the youngest
* -1: the youngest
* -2: the second youngest
* @return The child span at index `id`, or NULL if the ID does not exist
*/
lv_span_t * lv_spangroup_get_child(const lv_obj_t * obj, int32_t id);
/**
*
* @param obj The spangroup object to get the child count of.
* @return The span count of the spangroup.
*/
uint32_t lv_spangroup_get_child_cnt(const lv_obj_t * obj);
/**
* get the align of the spangroup.
* @param obj pointer to a spangroup object.

View File

@@ -34,6 +34,24 @@
**********************/
static lv_obj_tree_walk_res_t invalidate_layout_cb(lv_obj_t * obj, void * user_data);
static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x,
lv_coord_t y,
lv_color_t color, lv_opa_t opa);
static void set_px_cb_alpha1(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa);
static void set_px_cb_alpha2(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa);
static void set_px_cb_alpha4(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa);
static void set_px_cb_alpha8(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa);
static void set_px_alpha_generic(lv_img_dsc_t * d, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa);
/**********************
* STATIC VARIABLES
**********************/
@@ -218,9 +236,6 @@ void lv_disp_remove(lv_disp_t * disp)
indev = lv_indev_get_next(indev);
}
_lv_ll_remove(&LV_GC_ROOT(_lv_disp_ll), disp);
lv_timer_del(disp->refr_timer);
/** delete screen and other obj */
if (disp->sys_layer) {
lv_obj_del(disp->sys_layer);
@@ -234,6 +249,9 @@ void lv_disp_remove(lv_disp_t * disp)
/*Delete the screenst*/
lv_obj_del(disp->screens[0]);
}
_lv_ll_remove(&LV_GC_ROOT(_lv_disp_ll), disp);
lv_timer_del(disp->refr_timer);
lv_mem_free(disp);
if(was_default) lv_disp_set_default(_lv_ll_get_head(&LV_GC_ROOT(_lv_disp_ll)));
@@ -403,6 +421,29 @@ lv_disp_rot_t lv_disp_get_rotation(lv_disp_t * disp)
return disp->driver->rotated;
}
void lv_disp_drv_use_generic_set_px_cb(lv_disp_drv_t * disp_drv, lv_img_cf_t cf)
{
switch(cf) {
case LV_IMG_CF_TRUE_COLOR_ALPHA:
disp_drv->set_px_cb = set_px_true_color_alpha;
break;
case LV_IMG_CF_ALPHA_1BIT:
disp_drv->set_px_cb = set_px_cb_alpha1;
break;
case LV_IMG_CF_ALPHA_2BIT:
disp_drv->set_px_cb = set_px_cb_alpha2;
break;
case LV_IMG_CF_ALPHA_4BIT:
disp_drv->set_px_cb = set_px_cb_alpha4;
break;
case LV_IMG_CF_ALPHA_8BIT:
disp_drv->set_px_cb = set_px_cb_alpha8;
break;
default:
disp_drv->set_px_cb = NULL;
}
}
/**********************
* STATIC FUNCTIONS
**********************/
@@ -413,3 +454,99 @@ static lv_obj_tree_walk_res_t invalidate_layout_cb(lv_obj_t * obj, void * user_d
lv_obj_mark_layout_as_dirty(obj);
return LV_OBJ_TREE_WALK_NEXT;
}
static void set_px_cb_alpha1(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa)
{
(void) disp_drv; /*Unused*/
if(opa <= LV_OPA_MIN) return;
lv_img_dsc_t d;
d.data = buf;
d.header.w = buf_w;
d.header.cf = LV_IMG_CF_ALPHA_1BIT;
set_px_alpha_generic(&d, x, y, color, opa);
}
static void set_px_cb_alpha2(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa)
{
(void) disp_drv; /*Unused*/
if(opa <= LV_OPA_MIN) return;
lv_img_dsc_t d;
d.data = buf;
d.header.w = buf_w;
d.header.cf = LV_IMG_CF_ALPHA_2BIT;
set_px_alpha_generic(&d, x, y, color, opa);
}
static void set_px_cb_alpha4(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa)
{
(void) disp_drv; /*Unused*/
if(opa <= LV_OPA_MIN) return;
lv_img_dsc_t d;
d.data = buf;
d.header.w = buf_w;
d.header.cf = LV_IMG_CF_ALPHA_4BIT;
set_px_alpha_generic(&d, x, y, color, opa);
}
static void set_px_cb_alpha8(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa)
{
(void) disp_drv; /*Unused*/
if(opa <= LV_OPA_MIN) return;
lv_img_dsc_t d;
d.data = buf;
d.header.w = buf_w;
d.header.cf = LV_IMG_CF_ALPHA_8BIT;
set_px_alpha_generic(&d, x, y, color, opa);
}
static void set_px_alpha_generic(lv_img_dsc_t * d, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa)
{
d->header.always_zero = 0;
d->header.h = 1; /*Doesn't matter*/
uint8_t br = lv_color_brightness(color);
if(opa < LV_OPA_MAX) {
uint8_t bg = lv_img_buf_get_px_alpha(d, x, y);
br = (uint16_t)((uint16_t)br * opa + (bg * (255 - opa))) >> 8;
}
lv_img_buf_set_px_alpha(d, x, y, br);
}
static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x,
lv_coord_t y,
lv_color_t color, lv_opa_t opa)
{
(void) disp_drv; /*Unused*/
if(opa <= LV_OPA_MIN) return;
lv_img_dsc_t d;
d.data = buf;
d.header.always_zero = 0;
d.header.h = 1; /*Doesn't matter*/;
d.header.w = buf_w;
d.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
lv_color_t bg_color = lv_img_buf_get_px_color(&d, x, y, lv_color_black());
lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&d, x, y);
lv_opa_t res_opa;
lv_color_t res_color;
lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &res_opa);
lv_img_buf_set_px_alpha(&d, x, y, res_opa);
lv_img_buf_set_px_color(&d, x, y, res_color);
}

View File

@@ -18,6 +18,7 @@ extern "C" {
#include <stdint.h>
#include <stdbool.h>
#include "lv_hal.h"
#include "../draw/lv_img_buf.h"
#include "../misc/lv_color.h"
#include "../misc/lv_area.h"
#include "../misc/lv_ll.h"
@@ -312,6 +313,8 @@ lv_disp_t * lv_disp_get_next(lv_disp_t * disp);
*/
lv_disp_draw_buf_t * lv_disp_get_draw_buf(lv_disp_t * disp);
void lv_disp_drv_use_generic_set_px_cb(lv_disp_drv_t * disp_drv, lv_img_cf_t cf);
/**********************
* MACROS
**********************/

View File

@@ -81,7 +81,7 @@ typedef struct {
int16_t enc_diff; /**< For LV_INDEV_TYPE_ENCODER number of steps since the previous read*/
lv_indev_state_t state; /**< LV_INDEV_STATE_REL or LV_INDEV_STATE_PR*/
bool continue_reading; /**< Call the read callback until it's set to true*/
bool continue_reading; /**< If set to true, the read callback is invoked again*/
} lv_indev_data_t;
/** Initialized by the user and registered by 'lv_indev_add()'*/

View File

@@ -74,7 +74,7 @@
#endif
/*Enable more complex drawing routines to manage screens transparency.
*Can be used if the UI is above an other layer, e.g. an OSD menu or video player.
*Can be used if the UI is above another layer, e.g. an OSD menu or video player.
*Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to non LV_OPA_COVER value*/
#ifndef LV_COLOR_SCREEN_TRANSP
# ifdef CONFIG_LV_COLOR_SCREEN_TRANSP
@@ -585,6 +585,15 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
#endif
#endif /*LV_ENABLE_GC*/
/*1: Enable API to take snapshot for object*/
#ifndef LV_USE_SNAPSHOT
# ifdef CONFIG_LV_USE_SNAPSHOT
# define LV_USE_SNAPSHOT CONFIG_LV_USE_SNAPSHOT
# else
# define LV_USE_SNAPSHOT 1
# endif
#endif
/*=====================
* COMPILER SETTINGS
*====================*/

168
src/misc/lv_anim_timeline.c Normal file
View File

@@ -0,0 +1,168 @@
/**
* @file lv_anim_timeline.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_anim_timeline.h"
#include "lv_mem.h"
#include "../misc/lv_assert.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/*Data of anim_timeline_dsc*/
typedef struct{
lv_anim_t anim;
lv_anim_t * new_anim;
uint32_t start_time;
}lv_anim_timeline_dsc_t;
/*Data of anim_timeline*/
struct _lv_anim_timeline_t{
lv_anim_timeline_dsc_t * anim_dsc; /**< Dynamically allocated anim dsc array*/
uint32_t anim_dsc_cnt; /**< The length of anim dsc array*/
bool reverse; /**< Reverse playback*/
};
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_anim_timeline_t * lv_anim_timeline_create(void)
{
lv_anim_timeline_t * at = (lv_anim_timeline_t *)lv_mem_alloc(sizeof(lv_anim_timeline_t));
LV_ASSERT_MALLOC(at);
if(at) lv_memset_00(at, sizeof(lv_anim_timeline_t));
return at;
}
void lv_anim_timeline_del(lv_anim_timeline_t * at)
{
LV_ASSERT_NULL(at);
for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) {
lv_anim_t * a = &(at->anim_dsc[i].anim);
lv_anim_custom_del(at->anim_dsc[i].new_anim, (lv_anim_custom_exec_cb_t)a->exec_cb);
}
lv_mem_free(at->anim_dsc);
lv_mem_free(at);
}
void lv_anim_timeline_add(lv_anim_timeline_t * at, uint32_t start_time, lv_anim_t * a)
{
LV_ASSERT_NULL(at);
at->anim_dsc_cnt++;
at->anim_dsc = lv_mem_realloc(at->anim_dsc, at->anim_dsc_cnt * sizeof(lv_anim_timeline_dsc_t));
LV_ASSERT_MALLOC(at->anim_dsc);
at->anim_dsc[at->anim_dsc_cnt - 1].anim = *a;
at->anim_dsc[at->anim_dsc_cnt - 1].new_anim = NULL;
at->anim_dsc[at->anim_dsc_cnt - 1].start_time = start_time;
}
uint32_t lv_anim_timeline_start(lv_anim_timeline_t * at)
{
LV_ASSERT_NULL(at);
const uint32_t playtime = lv_anim_timeline_get_playtime(at);
bool reverse = at->reverse;
for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) {
lv_anim_t a = at->anim_dsc[i].anim;
uint32_t start_time = at->anim_dsc[i].start_time;
if(reverse) {
int32_t temp = a.start_value;
a.start_value = a.end_value;
a.end_value = temp;
lv_anim_set_delay(&a, playtime - (start_time + a.time));
}
else {
lv_anim_set_delay(&a, start_time);
}
at->anim_dsc[i].new_anim = lv_anim_start(&a);
}
return playtime;
}
void lv_anim_timeline_set_reverse(lv_anim_timeline_t * at, bool reverse)
{
LV_ASSERT_NULL(at);
at->reverse = reverse;
}
void lv_anim_timeline_set_progress(lv_anim_timeline_t * at, uint16_t progress)
{
LV_ASSERT_NULL(at);
const uint32_t playtime = lv_anim_timeline_get_playtime(at);
const uint32_t act_time = progress * playtime / 0xFFFF;
for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) {
lv_anim_t * a = &(at->anim_dsc[i].anim);
uint32_t start_time = at->anim_dsc[i].start_time;
int32_t value = 0;
if(act_time < start_time) {
value = a->start_value;
}
else if(act_time < (start_time + a->time)) {
a->act_time = act_time - start_time;
value = a->path_cb(a);
}
else {
value = a->end_value;
}
a->exec_cb(a->var, value);
}
}
uint32_t lv_anim_timeline_get_playtime(lv_anim_timeline_t * at)
{
LV_ASSERT_NULL(at);
uint32_t playtime = 0;
for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) {
uint32_t end = at->anim_dsc[i].start_time + at->anim_dsc[i].anim.time;
if(end > playtime) {
playtime = end;
}
}
return playtime;
}
bool lv_anim_timeline_get_reverse(lv_anim_timeline_t * at)
{
LV_ASSERT_NULL(at);
return at->reverse;
}

View File

@@ -0,0 +1,97 @@
/**
* @file lv_anim_timeline.h
*
*/
#ifndef LV_ANIM_TIMELINE_H
#define LV_ANIM_TIMELINE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_anim.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct _lv_anim_timeline_t;
typedef struct _lv_anim_timeline_t lv_anim_timeline_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Create a animation timeline.
* @return pointer to the animation timeline.
*/
lv_anim_timeline_t * lv_anim_timeline_create(void);
/**
* Delete animation timeline.
* @param at pointer to the animation timeline.
*/
void lv_anim_timeline_del(lv_anim_timeline_t * at);
/**
* Add animation to the animation timeline.
* @param at pointer to the animation timeline.
* @param start_time the time the animation started on the timeline, note that start_time will override the value of delay.
* @param a pointer to an animation.
*/
void lv_anim_timeline_add(lv_anim_timeline_t * at, uint32_t start_time, lv_anim_t * a);
/**
* Start the animation timeline.
* @param at pointer to the animation timeline.
* @return total time spent in animation timeline.
*/
uint32_t lv_anim_timeline_start(lv_anim_timeline_t * at);
/**
* Set the playback direction of the animation timeline.
* @param at pointer to the animation timeline.
* @param reverse whether to play in reverse.
*/
void lv_anim_timeline_set_reverse(lv_anim_timeline_t * at, bool reverse);
/**
* Set the progress of the animation timeline.
* @param at pointer to the animation timeline.
* @param progress set value 0~65535 to map 0~100% animation progress.
*/
void lv_anim_timeline_set_progress(lv_anim_timeline_t * at, uint16_t progress);
/**
* Get the time used to play the animation timeline.
* @param at pointer to the animation timeline.
* @return total time spent in animation timeline.
*/
uint32_t lv_anim_timeline_get_playtime(lv_anim_timeline_t * at);
/**
* Get whether the animation timeline is played in reverse.
* @param at pointer to the animation timeline.
* @return return true if it is reverse playback.
*/
bool lv_anim_timeline_get_reverse(lv_anim_timeline_t * at);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_ANIM_TIMELINE_H*/

View File

@@ -1,4 +1,5 @@
CSRCS += lv_anim.c
CSRCS += lv_anim_timeline.c
CSRCS += lv_area.c
CSRCS += lv_async.c
CSRCS += lv_bidi.c

View File

@@ -27,25 +27,6 @@
* STATIC PROTOTYPES
**********************/
static void lv_canvas_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
static void set_set_px_cb(lv_disp_drv_t * disp_drv, lv_img_cf_t cf);
static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x,
lv_coord_t y,
lv_color_t color, lv_opa_t opa);
static void set_px_cb_alpha1(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa);
static void set_px_cb_alpha2(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa);
static void set_px_cb_alpha4(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa);
static void set_px_cb_alpha8(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa);
static void set_px_alpha_generic(lv_img_dsc_t * d, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa);
/**********************
* STATIC VARIABLES
@@ -595,7 +576,7 @@ void lv_canvas_draw_rect(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord
disp.driver->hor_res = dsc->header.w;
disp.driver->ver_res = dsc->header.h;
set_set_px_cb(disp.driver, dsc->header.cf);
lv_disp_drv_use_generic_set_px_cb(disp.driver, dsc->header.cf);
/*Disable anti-aliasing if drawing with transparent color to chroma keyed canvas*/
lv_color_t ctransp = LV_COLOR_CHROMA_KEY;
@@ -656,7 +637,7 @@ void lv_canvas_draw_text(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord
disp.driver->hor_res = dsc->header.w;
disp.driver->ver_res = dsc->header.h;
set_set_px_cb(disp.driver, dsc->header.cf);
lv_disp_drv_use_generic_set_px_cb(disp.driver, dsc->header.cf);
lv_disp_t * refr_ori = _lv_refr_get_disp_refreshing();
_lv_refr_set_disp_refreshing(&disp);
@@ -717,7 +698,7 @@ void lv_canvas_draw_img(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, const voi
disp.driver->hor_res = dsc->header.w;
disp.driver->ver_res = dsc->header.h;
set_set_px_cb(disp.driver, dsc->header.cf);
lv_disp_drv_use_generic_set_px_cb(disp.driver, dsc->header.cf);
lv_disp_t * refr_ori = _lv_refr_get_disp_refreshing();
_lv_refr_set_disp_refreshing(&disp);
@@ -764,7 +745,7 @@ void lv_canvas_draw_line(lv_obj_t * canvas, const lv_point_t points[], uint32_t
disp.driver->hor_res = dsc->header.w;
disp.driver->ver_res = dsc->header.h;
set_set_px_cb(disp.driver, dsc->header.cf);
lv_disp_drv_use_generic_set_px_cb(disp.driver, dsc->header.cf);
/*Disable anti-aliasing if drawing with transparent color to chroma keyed canvas*/
lv_color_t ctransp = LV_COLOR_CHROMA_KEY;
@@ -822,7 +803,7 @@ void lv_canvas_draw_polygon(lv_obj_t * canvas, const lv_point_t points[], uint32
disp.driver->hor_res = dsc->header.w;
disp.driver->ver_res = dsc->header.h;
set_set_px_cb(disp.driver, dsc->header.cf);
lv_disp_drv_use_generic_set_px_cb(disp.driver, dsc->header.cf);
/*Disable anti-aliasing if drawing with transparent color to chroma keyed canvas*/
lv_color_t ctransp = LV_COLOR_CHROMA_KEY;
@@ -878,7 +859,7 @@ void lv_canvas_draw_arc(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_
disp.driver->hor_res = dsc->header.w;
disp.driver->ver_res = dsc->header.h;
set_set_px_cb(disp.driver, dsc->header.cf);
lv_disp_drv_use_generic_set_px_cb(disp.driver, dsc->header.cf);
/*Disable anti-aliasing if drawing with transparent color to chroma keyed canvas*/
lv_color_t ctransp = LV_COLOR_CHROMA_KEY;
@@ -930,123 +911,4 @@ static void lv_canvas_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj
LV_TRACE_OBJ_CREATE("finished");
}
static void set_set_px_cb(lv_disp_drv_t * disp_drv, lv_img_cf_t cf)
{
switch(cf) {
case LV_IMG_CF_TRUE_COLOR_ALPHA:
disp_drv->set_px_cb = set_px_true_color_alpha;
break;
case LV_IMG_CF_ALPHA_1BIT:
disp_drv->set_px_cb = set_px_cb_alpha1;
break;
case LV_IMG_CF_ALPHA_2BIT:
disp_drv->set_px_cb = set_px_cb_alpha2;
break;
case LV_IMG_CF_ALPHA_4BIT:
disp_drv->set_px_cb = set_px_cb_alpha4;
break;
case LV_IMG_CF_ALPHA_8BIT:
disp_drv->set_px_cb = set_px_cb_alpha8;
break;
default:
disp_drv->set_px_cb = NULL;
}
}
static void set_px_cb_alpha1(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa)
{
(void) disp_drv; /*Unused*/
if(opa <= LV_OPA_MIN) return;
lv_img_dsc_t d;
d.data = buf;
d.header.w = buf_w;
d.header.cf = LV_IMG_CF_ALPHA_1BIT;
set_px_alpha_generic(&d, x, y, color, opa);
}
static void set_px_cb_alpha2(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa)
{
(void) disp_drv; /*Unused*/
if(opa <= LV_OPA_MIN) return;
lv_img_dsc_t d;
d.data = buf;
d.header.w = buf_w;
d.header.cf = LV_IMG_CF_ALPHA_2BIT;
set_px_alpha_generic(&d, x, y, color, opa);
}
static void set_px_cb_alpha4(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa)
{
(void) disp_drv; /*Unused*/
if(opa <= LV_OPA_MIN) return;
lv_img_dsc_t d;
d.data = buf;
d.header.w = buf_w;
d.header.cf = LV_IMG_CF_ALPHA_4BIT;
set_px_alpha_generic(&d, x, y, color, opa);
}
static void set_px_cb_alpha8(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa)
{
(void) disp_drv; /*Unused*/
if(opa <= LV_OPA_MIN) return;
lv_img_dsc_t d;
d.data = buf;
d.header.w = buf_w;
d.header.cf = LV_IMG_CF_ALPHA_8BIT;
set_px_alpha_generic(&d, x, y, color, opa);
}
static void set_px_alpha_generic(lv_img_dsc_t * d, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa)
{
d->header.always_zero = 0;
d->header.h = 1; /*Doesn't matter*/
uint8_t br = lv_color_brightness(color);
if(opa < LV_OPA_MAX) {
uint8_t bg = lv_img_buf_get_px_alpha(d, x, y);
br = (uint16_t)((uint16_t)br * opa + (bg * (255 - opa))) >> 8;
}
lv_img_buf_set_px_alpha(d, x, y, br);
}
static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x,
lv_coord_t y,
lv_color_t color, lv_opa_t opa)
{
(void) disp_drv; /*Unused*/
if(opa <= LV_OPA_MIN) return;
lv_img_dsc_t d;
d.data = buf;
d.header.always_zero = 0;
d.header.h = 1; /*Doesn't matter*/;
d.header.w = buf_w;
d.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
lv_color_t bg_color = lv_img_buf_get_px_color(&d, x, y, lv_color_black());
lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&d, x, y);
lv_opa_t res_opa;
lv_color_t res_color;
lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &res_opa);
lv_img_buf_set_px_alpha(&d, x, y, res_opa);
lv_img_buf_set_px_color(&d, x, y, res_color);
}
#endif