demo工程暂存 优化菜单界面UI和功能

This commit is contained in:
2024-04-29 16:32:24 +08:00
commit 330cd25cf1
3310 changed files with 2163318 additions and 0 deletions

View File

@ -0,0 +1,20 @@
CSRCS += lv_disp.c
CSRCS += lv_group.c
CSRCS += lv_indev.c
CSRCS += lv_indev_scroll.c
CSRCS += lv_obj.c
CSRCS += lv_obj_class.c
CSRCS += lv_obj_draw.c
CSRCS += lv_obj_pos.c
CSRCS += lv_obj_scroll.c
CSRCS += lv_obj_style.c
CSRCS += lv_obj_style_gen.c
CSRCS += lv_obj_tree.c
CSRCS += lv_event.c
CSRCS += lv_refr.c
CSRCS += lv_theme.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core"

View File

@ -0,0 +1,264 @@
/**
* @file lv_disp.h
*
*/
#ifndef LV_DISP_H
#define LV_DISP_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../hal/lv_hal.h"
#include "lv_obj.h"
#include "lv_theme.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef enum {
LV_SCR_LOAD_ANIM_NONE,
LV_SCR_LOAD_ANIM_OVER_LEFT,
LV_SCR_LOAD_ANIM_OVER_RIGHT,
LV_SCR_LOAD_ANIM_OVER_TOP,
LV_SCR_LOAD_ANIM_OVER_BOTTOM,
LV_SCR_LOAD_ANIM_MOVE_LEFT,
LV_SCR_LOAD_ANIM_MOVE_RIGHT,
LV_SCR_LOAD_ANIM_MOVE_TOP,
LV_SCR_LOAD_ANIM_MOVE_BOTTOM,
LV_SCR_LOAD_ANIM_FADE_IN,
LV_SCR_LOAD_ANIM_FADE_ON = LV_SCR_LOAD_ANIM_FADE_IN, /*For backward compatibility*/
LV_SCR_LOAD_ANIM_FADE_OUT,
LV_SCR_LOAD_ANIM_OUT_LEFT,
LV_SCR_LOAD_ANIM_OUT_RIGHT,
LV_SCR_LOAD_ANIM_OUT_TOP,
LV_SCR_LOAD_ANIM_OUT_BOTTOM,
} lv_scr_load_anim_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Return with a pointer to the active screen
* @param disp pointer to display which active screen should be get. (NULL to use the default
* screen)
* @return pointer to the active screen object (loaded by 'lv_scr_load()')
*/
lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp);
/**
* Return with a pointer to the previous screen. Only used during screen transitions.
* @param disp pointer to display which previous screen should be get. (NULL to use the default
* screen)
* @return pointer to the previous screen object or NULL if not used now
*/
lv_obj_t * lv_disp_get_scr_prev(lv_disp_t * disp);
/**
* Make a screen active
* @param scr pointer to a screen
*/
void lv_disp_load_scr(lv_obj_t * scr);
/**
* Return with the top layer. (Same on every screen and it is above the normal screen layer)
* @param disp pointer to display which top layer should be get. (NULL to use the default screen)
* @return pointer to the top layer object (transparent screen sized lv_obj)
*/
lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp);
/**
* Return with the sys. layer. (Same on every screen and it is above the normal screen and the top
* layer)
* @param disp pointer to display which sys. layer should be retrieved. (NULL to use the default screen)
* @return pointer to the sys layer object (transparent screen sized lv_obj)
*/
lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp);
/**
* Set the theme of a display
* @param disp pointer to a display
*/
void lv_disp_set_theme(lv_disp_t * disp, lv_theme_t * th);
/**
* Get the theme of a display
* @param disp pointer to a display
* @return the display's theme (can be NULL)
*/
lv_theme_t * lv_disp_get_theme(lv_disp_t * disp);
/**
* Set the background color of a display
* @param disp pointer to a display
* @param color color of the background
*/
void lv_disp_set_bg_color(lv_disp_t * disp, lv_color_t color);
/**
* Set the background image of a display
* @param disp pointer to a display
* @param img_src path to file or pointer to an `lv_img_dsc_t` variable
*/
void lv_disp_set_bg_image(lv_disp_t * disp, const void * img_src);
/**
* Set opacity of the background
* @param disp pointer to a display
* @param opa opacity (0..255)
*/
void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa);
/**
* Switch screen with animation
* @param scr pointer to the new screen to load
* @param anim_type type of the animation from `lv_scr_load_anim_t`, e.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT`
* @param time time of the animation
* @param delay delay before the transition
* @param auto_del true: automatically delete the old screen
*/
void lv_scr_load_anim(lv_obj_t * scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del);
/**
* Get elapsed time since last user activity on a display (e.g. click)
* @param disp pointer to a display (NULL to get the overall smallest inactivity)
* @return elapsed ticks (milliseconds) since the last activity
*/
uint32_t lv_disp_get_inactive_time(const lv_disp_t * disp);
/**
* Manually trigger an activity on a display
* @param disp pointer to a display (NULL to use the default display)
*/
void lv_disp_trig_activity(lv_disp_t * disp);
/**
* Clean any CPU cache that is related to the display.
* @param disp pointer to a display (NULL to use the default display)
*/
void lv_disp_clean_dcache(lv_disp_t * disp);
/**
* Temporarily enable and disable the invalidation of the display.
* @param disp pointer to a display (NULL to use the default display)
* @param en true: enable invalidation; false: invalidation
*/
void lv_disp_enable_invalidation(lv_disp_t * disp, bool en);
/**
* Get display invalidation is enabled.
* @param disp pointer to a display (NULL to use the default display)
* @return return true if invalidation is enabled
*/
bool lv_disp_is_invalidation_enabled(lv_disp_t * disp);
/**
* Get a pointer to the screen refresher timer to
* modify its parameters with `lv_timer_...` functions.
* @param disp pointer to a display
* @return pointer to the display refresher timer. (NULL on error)
*/
lv_timer_t * _lv_disp_get_refr_timer(lv_disp_t * disp);
/*------------------------------------------------
* To improve backward compatibility
* Recommended only if you have one display
*------------------------------------------------*/
/**
* Get the active screen of the default display
* @return pointer to the active screen
*/
static inline lv_obj_t * lv_scr_act(void)
{
return lv_disp_get_scr_act(lv_disp_get_default());
}
/**
* Get the top layer of the default display
* @return pointer to the top layer
*/
static inline lv_obj_t * lv_layer_top(void)
{
return lv_disp_get_layer_top(lv_disp_get_default());
}
/**
* Get the active screen of the default display
* @return pointer to the sys layer
*/
static inline lv_obj_t * lv_layer_sys(void)
{
return lv_disp_get_layer_sys(lv_disp_get_default());
}
static inline void lv_scr_load(lv_obj_t * scr)
{
lv_disp_load_scr(scr);
}
/**********************
* MACROS
**********************/
/*------------------------------------------------
* To improve backward compatibility
* Recommended only if you have one display
*------------------------------------------------*/
#ifndef LV_HOR_RES
/**
* The horizontal resolution of the currently active display.
*/
#define LV_HOR_RES lv_disp_get_hor_res(lv_disp_get_default())
#endif
#ifndef LV_VER_RES
/**
* The vertical resolution of the currently active display.
*/
#define LV_VER_RES lv_disp_get_ver_res(lv_disp_get_default())
#endif
/**
* Scale the given number of pixels (a distance or size) relative to a 160 DPI display
* considering the DPI of the default display.
* It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the
* DPI of the display.
* @param n the number of pixels to scale
* @return `n x current_dpi/160`
*/
static inline lv_coord_t lv_dpx(lv_coord_t n)
{
return LV_DPX(n);
}
/**
* Scale the given number of pixels (a distance or size) relative to a 160 DPI display
* considering the DPI of the given display.
* It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the
* DPI of the display.
* @param obj a display whose dpi should be considered
* @param n the number of pixels to scale
* @return `n x current_dpi/160`
*/
static inline lv_coord_t lv_disp_dpx(const lv_disp_t * disp, lv_coord_t n)
{
return _LV_DPX_CALC(lv_disp_get_dpi(disp), n);
}
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DISP_H*/

View File

@ -0,0 +1,376 @@
/**
* @file lv_event.h
*
*/
#ifndef LV_EVENT_H
#define LV_EVENT_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <stdbool.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct _lv_obj_t;
struct _lv_event_dsc_t;
/**
* Type of event being sent to the object.
*/
typedef enum {
LV_EVENT_ALL = 0,
/** Input device events*/
LV_EVENT_PRESSED, /**< The object has been pressed*/
LV_EVENT_PRESSING, /**< The object is being pressed (called continuously while pressing)*/
LV_EVENT_PRESS_LOST, /**< The object is still being pressed but slid cursor/finger off of the object */
LV_EVENT_SHORT_CLICKED, /**< The object was pressed for a short period of time, then released it. Not called if scrolled.*/
LV_EVENT_LONG_PRESSED, /**< Object has been pressed for at least `long_press_time`. Not called if scrolled.*/
LV_EVENT_LONG_PRESSED_REPEAT, /**< Called after `long_press_time` in every `long_press_repeat_time` ms. Not called if scrolled.*/
LV_EVENT_CLICKED, /**< Called on release if not scrolled (regardless to long press)*/
LV_EVENT_RELEASED, /**< Called in every cases when the object has been released*/
LV_EVENT_SCROLL_BEGIN, /**< Scrolling begins. The event parameter is a pointer to the animation of the scroll. Can be modified*/
LV_EVENT_SCROLL_END, /**< Scrolling ends*/
LV_EVENT_SCROLL, /**< Scrolling*/
LV_EVENT_GESTURE, /**< A gesture is detected. Get the gesture with `lv_indev_get_gesture_dir(lv_indev_get_act());` */
LV_EVENT_KEY, /**< A key is sent to the object. Get the key with `lv_indev_get_key(lv_indev_get_act());`*/
LV_EVENT_FOCUSED, /**< The object is focused*/
LV_EVENT_DEFOCUSED, /**< The object is defocused*/
LV_EVENT_LEAVE, /**< The object is defocused but still selected*/
LV_EVENT_HIT_TEST, /**< Perform advanced hit-testing*/
/** Drawing events*/
LV_EVENT_COVER_CHECK, /**< Check if the object fully covers an area. The event parameter is `lv_cover_check_info_t *`.*/
LV_EVENT_REFR_EXT_DRAW_SIZE, /**< Get the required extra draw area around the object (e.g. for shadow). The event parameter is `lv_coord_t *` to store the size.*/
LV_EVENT_DRAW_MAIN_BEGIN, /**< Starting the main drawing phase*/
LV_EVENT_DRAW_MAIN, /**< Perform the main drawing*/
LV_EVENT_DRAW_MAIN_END, /**< Finishing the main drawing phase*/
LV_EVENT_DRAW_POST_BEGIN, /**< Starting the post draw phase (when all children are drawn)*/
LV_EVENT_DRAW_POST, /**< Perform the post draw phase (when all children are drawn)*/
LV_EVENT_DRAW_POST_END, /**< Finishing the post draw phase (when all children are drawn)*/
LV_EVENT_DRAW_PART_BEGIN, /**< Starting to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */
LV_EVENT_DRAW_PART_END, /**< Finishing to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */
/** Special events*/
LV_EVENT_VALUE_CHANGED, /**< The object's value has changed (i.e. slider moved)*/
LV_EVENT_INSERT, /**< A text is inserted to the object. The event data is `char *` being inserted.*/
LV_EVENT_REFRESH, /**< Notify the object to refresh something on it (for the user)*/
LV_EVENT_READY, /**< A process has finished*/
LV_EVENT_CANCEL, /**< A process has been cancelled */
/** Other events*/
LV_EVENT_DELETE, /**< Object is being deleted*/
LV_EVENT_CHILD_CHANGED, /**< Child was removed, added, or its size, position were changed */
LV_EVENT_CHILD_CREATED, /**< Child was created, always bubbles up to all parents*/
LV_EVENT_CHILD_DELETED, /**< Child was deleted, always bubbles up to all parents*/
LV_EVENT_SCREEN_UNLOAD_START, /**< A screen unload started, fired immediately when scr_load is called*/
LV_EVENT_SCREEN_LOAD_START, /**< A screen load started, fired when the screen change delay is expired*/
LV_EVENT_SCREEN_LOADED, /**< A screen was loaded*/
LV_EVENT_SCREEN_UNLOADED, /**< A screen was unloaded*/
LV_EVENT_SIZE_CHANGED, /**< Object coordinates/size have changed*/
LV_EVENT_STYLE_CHANGED, /**< Object's style has changed*/
LV_EVENT_LAYOUT_CHANGED, /**< The children position has changed due to a layout recalculation*/
LV_EVENT_GET_SELF_SIZE, /**< Get the internal size of a widget*/
LV_EVENT_CALL_IN,
LV_EVENT_CALL_REJECT,
LV_EVENT_CALL_OK,
LV_EVENT_SCROLL_PREDICT,
LV_EVENT_ANCS_MSG_IN,
LV_EVENT_MSUIC_CONTEXT_IN,
LV_EVENT_CALL_HANDUP,
LV_EVENT_SCREENSAVER_IN,
LV_EVENT_FLEXIBLE_IN,
_LV_EVENT_LAST, /** Number of default events*/
LV_EVENT_PREPROCESS = 0x80, /** This is a flag that can be set with an event so it's processed
before the class default event processing */
} lv_event_code_t;
typedef struct _lv_event_t {
struct _lv_obj_t * target;
struct _lv_obj_t * current_target;
lv_event_code_t code;
void * user_data;
void * param;
struct _lv_event_t * prev;
uint8_t deleted : 1;
uint8_t stop_processing : 1;
uint8_t stop_bubbling : 1;
} lv_event_t;
/**
* @brief Event callback.
* Events are used to notify the user of some action being taken on the object.
* For details, see ::lv_event_t.
*/
typedef void (*lv_event_cb_t)(lv_event_t * e);
/**
* Used as the event parameter of ::LV_EVENT_HIT_TEST to check if an `point` can click the object or not.
* `res` should be set like this:
* - If already set to `false` an other event wants that point non clickable. If you want to respect it leave it as `false` or set `true` to overwrite it.
* - If already set `true` and `point` shouldn't be clickable set to `false`
* - If already set to `true` you agree that `point` can click the object leave it as `true`
*/
typedef struct {
const lv_point_t * point; /**< A point relative to screen to check if it can click the object or not*/
bool res; /**< true: `point` can click the object; false: it cannot*/
} lv_hit_test_info_t;
/**
* Used as the event parameter of ::LV_EVENT_COVER_CHECK to check if an area is covered by the object or not.
* In the event use `const lv_area_t * area = lv_event_get_cover_area(e)` to get the area to check
* and `lv_event_set_cover_res(e, res)` to set the result.
*/
typedef struct {
lv_cover_res_t res;
const lv_area_t * area;
} lv_cover_check_info_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Send an event to the object
* @param obj pointer to an object
* @param event_code the type of the event from `lv_event_t`
* @param param arbitrary data depending on the widget type and the event. (Usually `NULL`)
* @return LV_RES_OK: `obj` was not deleted in the event; LV_RES_INV: `obj` was deleted in the event_code
*/
lv_res_t lv_event_send(struct _lv_obj_t * obj, lv_event_code_t event_code, void * param);
/**
* Used by the widgets internally to call the ancestor widget types's event handler
* @param class_p pointer to the class of the widget (NOT the ancestor class)
* @param e pointer to the event descriptor
* @return LV_RES_OK: the target object was not deleted in the event; LV_RES_INV: it was deleted in the event_code
*/
lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e);
/**
* Get the object originally targeted by the event. It's the same even if the event is bubbled.
* @param e pointer to the event descriptor
* @return the target of the event_code
*/
struct _lv_obj_t * lv_event_get_target(lv_event_t * e);
/**
* Get the current target of the event. It's the object which event handler being called.
* If the event is not bubbled it's the same as "normal" target.
* @param e pointer to the event descriptor
* @return pointer to the current target of the event_code
*/
struct _lv_obj_t * lv_event_get_current_target(lv_event_t * e);
/**
* Get the event code of an event
* @param e pointer to the event descriptor
* @return the event code. (E.g. `LV_EVENT_CLICKED`, `LV_EVENT_FOCUSED`, etc)
*/
lv_event_code_t lv_event_get_code(lv_event_t * e);
/**
* Get the parameter passed when the event was sent
* @param e pointer to the event descriptor
* @return pointer to the parameter
*/
void * lv_event_get_param(lv_event_t * e);
/**
* Get the user_data passed when the event was registered on the object
* @param e pointer to the event descriptor
* @return pointer to the user_data
*/
void * lv_event_get_user_data(lv_event_t * e);
/**
* Stop the event from bubbling.
* This is only valid when called in the middle of an event processing chain.
* @param e pointer to the event descriptor
*/
void lv_event_stop_bubbling(lv_event_t * e);
/**
* Stop processing this event.
* This is only valid when called in the middle of an event processing chain.
* @param e pointer to the event descriptor
*/
void lv_event_stop_processing(lv_event_t * e);
/**
* Register a new, custom event ID.
* It can be used the same way as e.g. `LV_EVENT_CLICKED` to send custom events
* @return the new event id
* @example
* uint32_t LV_EVENT_MINE = 0;
* ...
* e = lv_event_register_id();
* ...
* lv_event_send(obj, LV_EVENT_MINE, &some_data);
*/
uint32_t lv_event_register_id(void);
/**
* Nested events can be called and one of them might belong to an object that is being deleted.
* Mark this object's `event_temp_data` deleted to know that its `lv_event_send` should return `LV_RES_INV`
* @param obj pointer to an object to mark as deleted
*/
void _lv_event_mark_deleted(struct _lv_obj_t * obj);
/**
* Add an event handler function for an object.
* Used by the user to react on event which happens with the object.
* An object can have multiple event handler. They will be called in the same order as they were added.
* @param obj pointer to an object
* @param filter and event code (e.g. `LV_EVENT_CLICKED`) on which the event should be called. `LV_EVENT_ALL` can be sued the receive all the events.
* @param event_cb the new event function
* @param user_data custom data data will be available in `event_cb`
* @return a pointer the event descriptor. Can be used in ::lv_obj_remove_event_dsc
*/
struct _lv_event_dsc_t * lv_obj_add_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter,
void * user_data);
/**
* Remove an event handler function for an object.
* @param obj pointer to an object
* @param event_cb the event function to remove, or `NULL` to remove the firstly added event callback
* @return true if any event handlers were removed
*/
bool lv_obj_remove_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb);
/**
* Remove an event handler function with a specific user_data from an object.
* @param obj pointer to an object
* @param event_cb the event function to remove, or `NULL` only `user_data` matters.
* @param event_user_data the user_data specified in ::lv_obj_add_event_cb
* @return true if any event handlers were removed
*/
bool lv_obj_remove_event_cb_with_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb,
const void * event_user_data);
/**
* DEPRECATED because doesn't work if multiple event handlers are added to an object.
* Remove an event handler function for an object.
* @param obj pointer to an object
* @param event_dsc pointer to an event descriptor to remove (returned by ::lv_obj_add_event_cb)
* @return true if any event handlers were removed
*/
bool lv_obj_remove_event_dsc(struct _lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc);
/**
* The user data of an event object event callback. Always the first match with `event_cb` will be returned.
* @param obj pointer to an object
* @param event_cb the event function
* @return the user_data
*/
void * lv_obj_get_event_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb);
/**
* Get the input device passed as parameter to indev related events.
* @param e pointer to an event
* @return the indev that triggered the event or NULL if called on a not indev related event
*/
lv_indev_t * lv_event_get_indev(lv_event_t * e);
/**
* Get the part draw descriptor passed as parameter to `LV_EVENT_DRAW_PART_BEGIN/END`.
* @param e pointer to an event
* @return the part draw descriptor to hook the drawing or NULL if called on an unrelated event
*/
lv_obj_draw_part_dsc_t * lv_event_get_draw_part_dsc(lv_event_t * e);
/**
* Get the draw context which should be the first parameter of the draw functions.
* Namely: `LV_EVENT_DRAW_MAIN/POST`, `LV_EVENT_DRAW_MAIN/POST_BEGIN`, `LV_EVENT_DRAW_MAIN/POST_END`
* @param e pointer to an event
* @return pointer to a draw context or NULL if called on an unrelated event
*/
lv_draw_ctx_t * lv_event_get_draw_ctx(lv_event_t * e);
/**
* Get the old area of the object before its size was changed. Can be used in `LV_EVENT_SIZE_CHANGED`
* @param e pointer to an event
* @return the old absolute area of the object or NULL if called on an unrelated event
*/
const lv_area_t * lv_event_get_old_size(lv_event_t * e);
/**
* Get the key passed as parameter to an event. Can be used in `LV_EVENT_KEY`
* @param e pointer to an event
* @return the triggering key or NULL if called on an unrelated event
*/
uint32_t lv_event_get_key(lv_event_t * e);
/**
* Get the animation descriptor of a scrolling. Can be used in `LV_EVENT_SCROLL_BEGIN`
* @param e pointer to an event
* @return the animation that will scroll the object. (can be modified as required)
*/
lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e);
/**
* Set the new extra draw size. Can be used in `LV_EVENT_REFR_EXT_DRAW_SIZE`
* @param e pointer to an event
* @param size The new extra draw size
*/
void lv_event_set_ext_draw_size(lv_event_t * e, lv_coord_t size);
/**
* Get a pointer to an `lv_point_t` variable in which the self size should be saved (width in `point->x` and height `point->y`).
* Can be used in `LV_EVENT_GET_SELF_SIZE`
* @param e pointer to an event
* @return pointer to `lv_point_t` or NULL if called on an unrelated event
*/
lv_point_t * lv_event_get_self_size_info(lv_event_t * e);
/**
* Get a pointer to an `lv_hit_test_info_t` variable in which the hit test result should be saved. Can be used in `LV_EVENT_HIT_TEST`
* @param e pointer to an event
* @return pointer to `lv_hit_test_info_t` or NULL if called on an unrelated event
*/
lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e);
/**
* Get a pointer to an area which should be examined whether the object fully covers it or not.
* Can be used in `LV_EVENT_HIT_TEST`
* @param e pointer to an event
* @return an area with absolute coordinates to check
*/
const lv_area_t * lv_event_get_cover_area(lv_event_t * e);
/**
* Set the result of cover checking. Can be used in `LV_EVENT_COVER_CHECK`
* @param e pointer to an event
* @param res an element of ::lv_cover_check_info_t
*/
void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_EVENT_H*/

View File

@ -0,0 +1,266 @@
/**
* @file lv_group.h
*
*/
#ifndef LV_GROUP_H
#define LV_GROUP_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#include <stdint.h>
#include <stdbool.h>
#include "../misc/lv_ll.h"
#include "../misc/lv_types.h"
/*********************
* DEFINES
*********************/
/*Predefined keys to control the focused object via lv_group_send(group, c)*/
enum {
LV_KEY_UP = 17, /*0x11*/
LV_KEY_DOWN = 18, /*0x12*/
LV_KEY_RIGHT = 19, /*0x13*/
LV_KEY_LEFT = 20, /*0x14*/
LV_KEY_ESC = 27, /*0x1B*/
LV_KEY_DEL = 127, /*0x7F*/
LV_KEY_BACKSPACE = 8, /*0x08*/
LV_KEY_ENTER = 10, /*0x0A, '\n'*/
LV_KEY_NEXT = 9, /*0x09, '\t'*/
LV_KEY_PREV = 11, /*0x0B, '*/
LV_KEY_HOME = 2, /*0x02, STX*/
LV_KEY_END = 3, /*0x03, ETX*/
};
typedef uint8_t lv_key_t;
/**********************
* TYPEDEFS
**********************/
struct _lv_obj_t;
struct _lv_group_t;
typedef void (*lv_group_focus_cb_t)(struct _lv_group_t *);
typedef void (*lv_group_edge_cb_t)(struct _lv_group_t *, bool);
/**
* Groups can be used to logically hold objects so that they can be individually focused.
* They are NOT for laying out objects on a screen (try layouts for that).
*/
typedef struct _lv_group_t {
lv_ll_t obj_ll; /**< Linked list to store the objects in the group*/
struct _lv_obj_t ** obj_focus; /**< The object in focus*/
lv_group_focus_cb_t focus_cb; /**< A function to call when a new object is focused (optional)*/
lv_group_edge_cb_t edge_cb; /**< A function to call when an edge is reached, no more focus
targets are available in this direction (to allow edge feedback
like a sound or a scroll bounce) */
#if LV_USE_USER_DATA
void * user_data;
#endif
uint8_t frozen : 1; /**< 1: can't focus to new object*/
uint8_t editing : 1; /**< 1: Edit mode, 0: Navigate mode*/
uint8_t refocus_policy : 1; /**< 1: Focus prev if focused on deletion. 0: Focus next if focused on
deletion.*/
uint8_t wrap : 1; /**< 1: Focus next/prev can wrap at end of list. 0: Focus next/prev stops at end
of list.*/
} lv_group_t;
typedef enum {
LV_GROUP_REFOCUS_POLICY_NEXT = 0,
LV_GROUP_REFOCUS_POLICY_PREV = 1
} lv_group_refocus_policy_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Init. the group module
* @remarks Internal function, do not call directly.
*/
void _lv_group_init(void);
/**
* Create a new object group
* @return pointer to the new object group
*/
lv_group_t * lv_group_create(void);
/**
* Delete a group object
* @param group pointer to a group
*/
void lv_group_del(lv_group_t * group);
/**
* Set a default group. New object are added to this group if it's enabled in their class with `add_to_def_group = true`
* @param group pointer to a group (can be `NULL`)
*/
void lv_group_set_default(lv_group_t * group);
/**
* Get the default group
* @return pointer to the default group
*/
lv_group_t * lv_group_get_default(void);
/**
* Add an object to a group
* @param group pointer to a group
* @param obj pointer to an object to add
*/
void lv_group_add_obj(lv_group_t * group, struct _lv_obj_t * obj);
/**
* Swap 2 object in a group. The object must be in the same group
* @param obj1 pointer to an object
* @param obj2 pointer to an other object
*/
void lv_group_swap_obj(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2);
/**
* Remove an object from its group
* @param obj pointer to an object to remove
*/
void lv_group_remove_obj(struct _lv_obj_t * obj);
/**
* Remove all objects from a group
* @param group pointer to a group
*/
void lv_group_remove_all_objs(lv_group_t * group);
/**
* Focus on an object (defocus the current)
* @param obj pointer to an object to focus on
*/
void lv_group_focus_obj(struct _lv_obj_t * obj);
/**
* Focus the next object in a group (defocus the current)
* @param group pointer to a group
*/
void lv_group_focus_next(lv_group_t * group);
/**
* Focus the previous object in a group (defocus the current)
* @param group pointer to a group
*/
void lv_group_focus_prev(lv_group_t * group);
/**
* Do not let to change the focus from the current object
* @param group pointer to a group
* @param en true: freeze, false: release freezing (normal mode)
*/
void lv_group_focus_freeze(lv_group_t * group, bool en);
/**
* Send a control character to the focuses object of a group
* @param group pointer to a group
* @param c a character (use LV_KEY_.. to navigate)
* @return result of focused object in group.
*/
lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c);
/**
* Set a function for a group which will be called when a new object is focused
* @param group pointer to a group
* @param focus_cb the call back function or NULL if unused
*/
void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb);
/**
* Set a function for a group which will be called when a focus edge is reached
* @param group pointer to a group
* @param edge_cb the call back function or NULL if unused
*/
void lv_group_set_edge_cb(lv_group_t * group, lv_group_edge_cb_t edge_cb);
/**
* Set whether the next or previous item in a group is focused if the currently focused obj is
* deleted.
* @param group pointer to a group
* @param policy new refocus policy enum
*/
void lv_group_set_refocus_policy(lv_group_t * group, lv_group_refocus_policy_t policy);
/**
* Manually set the current mode (edit or navigate).
* @param group pointer to group
* @param edit true: edit mode; false: navigate mode
*/
void lv_group_set_editing(lv_group_t * group, bool edit);
/**
* Set whether focus next/prev will allow wrapping from first->last or last->first object.
* @param group pointer to group
* @param en true: wrapping enabled; false: wrapping disabled
*/
void lv_group_set_wrap(lv_group_t * group, bool en);
/**
* Get the focused object or NULL if there isn't one
* @param group pointer to a group
* @return pointer to the focused object
*/
struct _lv_obj_t * lv_group_get_focused(const lv_group_t * group);
/**
* Get the focus callback function of a group
* @param group pointer to a group
* @return the call back function or NULL if not set
*/
lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group);
/**
* Get the edge callback function of a group
* @param group pointer to a group
* @return the call back function or NULL if not set
*/
lv_group_edge_cb_t lv_group_get_edge_cb(const lv_group_t * group);
/**
* Get the current mode (edit or navigate).
* @param group pointer to group
* @return true: edit mode; false: navigate mode
*/
bool lv_group_get_editing(const lv_group_t * group);
/**
* Get whether focus next/prev will allow wrapping from first->last or last->first object.
* @param group pointer to group
* @param en true: wrapping enabled; false: wrapping disabled
*/
bool lv_group_get_wrap(lv_group_t * group);
/**
* Get the number of object in the group
* @param group pointer to a group
* @return number of objects in the group
*/
uint32_t lv_group_get_obj_count(lv_group_t * group);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_GROUP_H*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,176 @@
/**
* @file lv_indev.h
*
*/
#ifndef LV_INDEV_H
#define LV_INDEV_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_obj.h"
#include "../hal/lv_hal_indev.h"
#include "lv_group.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Called periodically to read the input devices
* @param timer pointer to a timer to read
*/
void lv_indev_read_timer_cb(lv_timer_t * timer);
/**
* Enable or disable one or all input devices (default enabled)
* @param indev pointer to an input device or NULL to enable/disable all of them
* @param en true to enable, false to disable
*/
void lv_indev_enable(lv_indev_t * indev, bool en);
/**
* Get the currently processed input device. Can be used in action functions too.
* @return pointer to the currently processed input device or NULL if no input device processing
* right now
*/
lv_indev_t * lv_indev_get_act(void);
/**
* Get the type of an input device
* @param indev pointer to an input device
* @return the type of the input device from `lv_hal_indev_type_t` (`LV_INDEV_TYPE_...`)
*/
lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev);
/**
* Reset one or all input devices
* @param indev pointer to an input device to reset or NULL to reset all of them
* @param obj pointer to an object which triggers the reset.
*/
void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj);
/**
* Reset the long press state of an input device
* @param indev pointer to an input device
*/
void lv_indev_reset_long_press(lv_indev_t * indev);
/**
* Set a cursor for a pointer input device (for LV_INPUT_TYPE_POINTER and LV_INPUT_TYPE_BUTTON)
* @param indev pointer to an input device
* @param cur_obj pointer to an object to be used as cursor
*/
void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj);
/**
* Set a destination group for a keypad input device (for LV_INDEV_TYPE_KEYPAD)
* @param indev pointer to an input device
* @param group point to a group
*/
void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group);
/**
* Set the an array of points for LV_INDEV_TYPE_BUTTON.
* These points will be assigned to the buttons to press a specific point on the screen
* @param indev pointer to an input device
* @param group point to a group
*/
void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[]);
/**
* Get the last point of an input device (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
* @param indev pointer to an input device
* @param point pointer to a point to store the result
*/
void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point);
/**
* Get the current gesture direct
* @param indev pointer to an input device
* @return current gesture direct
*/
lv_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev);
/**
* Get the last pressed key of an input device (for LV_INDEV_TYPE_KEYPAD)
* @param indev pointer to an input device
* @return the last pressed key (0 on error)
*/
uint32_t lv_indev_get_key(const lv_indev_t * indev);
/**
* Check the current scroll direction of an input device (for LV_INDEV_TYPE_POINTER and
* LV_INDEV_TYPE_BUTTON)
* @param indev pointer to an input device
* @return LV_DIR_NONE: no scrolling now
* LV_DIR_HOR/VER
*/
lv_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev);
/**
* Get the currently scrolled object (for LV_INDEV_TYPE_POINTER and
* LV_INDEV_TYPE_BUTTON)
* @param indev pointer to an input device
* @return pointer to the currently scrolled object or NULL if no scrolling by this indev
*/
lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev);
/**
* Get the movement vector of an input device (for LV_INDEV_TYPE_POINTER and
* LV_INDEV_TYPE_BUTTON)
* @param indev pointer to an input device
* @param point pointer to a point to store the types.pointer.vector
*/
void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point);
/**
* Do nothing until the next release
* @param indev pointer to an input device
*/
void lv_indev_wait_release(lv_indev_t * indev);
/**
* Gets a pointer to the currently active object in the currently processed input device.
* @return pointer to currently active object or NULL if no active object
*/
lv_obj_t * lv_indev_get_obj_act(void);
/**
* Get a pointer to the indev read timer to
* modify its parameters with `lv_timer_...` functions.
* @param indev pointer to an input device
* @return pointer to the indev read refresher timer. (NULL on error)
*/
lv_timer_t * lv_indev_get_read_timer(lv_disp_t * indev);
/**
* Search the most top, clickable object by a point
* @param obj pointer to a start object, typically the screen
* @param point pointer to a point for searching the most top child
* @return pointer to the found object or NULL if there was no suitable object
*/
lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_INDEV_H*/

View File

@ -0,0 +1,65 @@
/**
* @file lv_indev_scroll.h
*
*/
#ifndef LV_INDEV_SCROLL_H
#define LV_INDEV_SCROLL_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_obj.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Handle scrolling. Called by LVGL during input device processing
* @param proc pointer to an input device's proc field
*/
void _lv_indev_scroll_handler(_lv_indev_proc_t * proc);
/**
* Handle throwing after scrolling. Called by LVGL during input device processing
* @param proc pointer to an input device's proc field
*/
void _lv_indev_scroll_throw_handler(_lv_indev_proc_t * proc);
/**
* Predict where would a scroll throw end
* @param indev pointer to an input device
* @param dir ` LV_DIR_VER` or `LV_DIR_HOR`
* @return the difference compared to the current position when the throw would be finished
*/
lv_coord_t lv_indev_scroll_throw_predict(lv_indev_t * indev, lv_dir_t dir);
/**
* Get the distance of the nearest snap point
* @param obj the object on which snap points should be found
* @param p save the distance of the found snap point there
*/
void lv_indev_scroll_get_snap_dist(lv_obj_t * obj, lv_point_t * p);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_INDEV_SCROLL_H*/

View File

@ -0,0 +1,410 @@
/**
* @file lv_obj.h
*
*/
#ifndef LV_OBJ_H
#define LV_OBJ_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#include <stddef.h>
#include <stdbool.h>
#include "../misc/lv_style.h"
#include "../misc/lv_types.h"
#include "../misc/lv_area.h"
#include "../misc/lv_color.h"
#include "../misc/lv_assert.h"
#include "../hal/lv_hal.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct _lv_obj_t;
/**
* Possible states of a widget.
* OR-ed values are possible
*/
enum {
LV_STATE_DEFAULT = 0x0000,
LV_STATE_CHECKED = 0x0001,
LV_STATE_FOCUSED = 0x0002,
LV_STATE_FOCUS_KEY = 0x0004,
LV_STATE_EDITED = 0x0008,
LV_STATE_HOVERED = 0x0010,
LV_STATE_PRESSED = 0x0020,
LV_STATE_SCROLLED = 0x0040,
LV_STATE_DISABLED = 0x0080,
LV_STATE_USER_1 = 0x1000,
LV_STATE_USER_2 = 0x2000,
LV_STATE_USER_3 = 0x4000,
LV_STATE_USER_4 = 0x8000,
LV_STATE_ANY = 0xFFFF, /**< Special value can be used in some functions to target all states*/
};
typedef uint16_t lv_state_t;
/**
* The possible parts of widgets.
* The parts can be considered as the internal building block of the widgets.
* E.g. slider = background + indicator + knob
* Not all parts are used by every widget
*/
enum {
LV_PART_MAIN = 0x000000, /**< A background like rectangle*/
LV_PART_SCROLLBAR = 0x010000, /**< The scrollbar(s)*/
LV_PART_INDICATOR = 0x020000, /**< Indicator, e.g. for slider, bar, switch, or the tick box of the checkbox*/
LV_PART_KNOB = 0x030000, /**< Like handle to grab to adjust the value*/
LV_PART_SELECTED = 0x040000, /**< Indicate the currently selected option or section*/
LV_PART_ITEMS = 0x050000, /**< Used if the widget has multiple similar elements (e.g. table cells)*/
LV_PART_TICKS = 0x060000, /**< Ticks on scale e.g. for a chart or meter*/
LV_PART_CURSOR = 0x070000, /**< Mark a specific place e.g. for text area's cursor or on a chart*/
LV_PART_CUSTOM_FIRST = 0x080000, /**< Extension point for custom widgets*/
LV_PART_ANY = 0x0F0000, /**< Special value can be used in some functions to target all parts*/
};
typedef uint32_t lv_part_t;
/**
* On/Off features controlling the object's behavior.
* OR-ed values are possible
*/
enum {
LV_OBJ_FLAG_HIDDEN = (1L << 0), /**< Make the object hidden. (Like it wasn't there at all)*/
LV_OBJ_FLAG_CLICKABLE = (1L << 1), /**< Make the object clickable by the input devices*/
LV_OBJ_FLAG_CLICK_FOCUSABLE = (1L << 2), /**< Add focused state to the object when clicked*/
LV_OBJ_FLAG_CHECKABLE = (1L << 3), /**< Toggle checked state when the object is clicked*/
LV_OBJ_FLAG_SCROLLABLE = (1L << 4), /**< Make the object scrollable*/
LV_OBJ_FLAG_SCROLL_ELASTIC = (1L << 5), /**< Allow scrolling inside but with slower speed*/
LV_OBJ_FLAG_SCROLL_MOMENTUM = (1L << 6), /**< Make the object scroll further when "thrown"*/
LV_OBJ_FLAG_SCROLL_ONE = (1L << 7), /**< Allow scrolling only one snappable children*/
LV_OBJ_FLAG_SCROLL_CHAIN_HOR = (1L << 8), /**< Allow propagating the horizontal scroll to a parent*/
LV_OBJ_FLAG_SCROLL_CHAIN_VER = (1L << 9), /**< Allow propagating the vertical scroll to a parent*/
LV_OBJ_FLAG_SCROLL_CHAIN = (LV_OBJ_FLAG_SCROLL_CHAIN_HOR | LV_OBJ_FLAG_SCROLL_CHAIN_VER),
LV_OBJ_FLAG_SCROLL_ON_FOCUS = (1L << 10), /**< Automatically scroll object to make it visible when focused*/
LV_OBJ_FLAG_SCROLL_WITH_ARROW = (1L << 11), /**< Allow scrolling the focused object with arrow keys*/
LV_OBJ_FLAG_SNAPPABLE = (1L << 12), /**< If scroll snap is enabled on the parent it can snap to this object*/
LV_OBJ_FLAG_PRESS_LOCK = (1L << 13), /**< Keep the object pressed even if the press slid from the object*/
LV_OBJ_FLAG_EVENT_BUBBLE = (1L << 14), /**< Propagate the events to the parent too*/
LV_OBJ_FLAG_GESTURE_BUBBLE = (1L << 15), /**< Propagate the gestures to the parent*/
LV_OBJ_FLAG_ADV_HITTEST = (1L << 16), /**< Allow performing more accurate hit (click) test. E.g. consider rounded corners.*/
LV_OBJ_FLAG_IGNORE_LAYOUT = (1L << 17), /**< Make the object position-able by the layouts*/
LV_OBJ_FLAG_FLOATING = (1L << 18), /**< Do not scroll the object when the parent scrolls and ignore layout*/
LV_OBJ_FLAG_OVERFLOW_VISIBLE = (1L << 19), /**< Do not clip the children's content to the parent's boundary*/
LV_OBJ_FLAG_LAYOUT_1 = (1L << 23), /**< Custom flag, free to use by layouts*/
LV_OBJ_FLAG_LAYOUT_2 = (1L << 24), /**< Custom flag, free to use by layouts*/
LV_OBJ_FLAG_WIDGET_1 = (1L << 25), /**< Custom flag, free to use by widget*/
LV_OBJ_FLAG_WIDGET_2 = (1L << 26), /**< Custom flag, free to use by widget*/
LV_OBJ_FLAG_USER_1 = (1L << 27), /**< Custom flag, free to use by user*/
LV_OBJ_FLAG_USER_2 = (1L << 28), /**< Custom flag, free to use by user*/
LV_OBJ_FLAG_USER_3 = (1L << 29), /**< Custom flag, free to use by user*/
LV_OBJ_FLAG_USER_4 = (1L << 30), /**< Custom flag, free to use by user*/
};
typedef uint32_t lv_obj_flag_t;
/**
* `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_obj_class`
* Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END`
*/
typedef enum {
LV_OBJ_DRAW_PART_RECTANGLE, /**< The main rectangle*/
LV_OBJ_DRAW_PART_BORDER_POST,/**< The border if style_border_post = true*/
LV_OBJ_DRAW_PART_SCROLLBAR, /**< The scrollbar*/
} lv_obj_draw_part_type_t;
#include "lv_obj_tree.h"
#include "lv_obj_pos.h"
#include "lv_obj_scroll.h"
#include "lv_obj_style.h"
#include "lv_obj_draw.h"
#include "lv_obj_class.h"
#include "lv_event.h"
#include "lv_group.h"
/**
* Make the base object's class publicly available.
*/
extern const lv_obj_class_t lv_obj_class;
/**
* Special, rarely used attributes.
* They are allocated automatically if any elements is set.
*/
typedef struct {
struct _lv_obj_t ** children; /**< Store the pointer of the children in an array.*/
uint32_t child_cnt; /**< Number of children*/
lv_group_t * group_p;
struct _lv_event_dsc_t * event_dsc; /**< Dynamically allocated event callback and user data array*/
lv_point_t scroll; /**< The current X/Y scroll offset*/
lv_coord_t ext_click_pad; /**< Extra click padding in all direction*/
lv_coord_t ext_draw_size; /**< EXTend the size in every direction for drawing.*/
lv_scrollbar_mode_t scrollbar_mode : 2; /**< How to display scrollbars*/
lv_scroll_snap_t scroll_snap_x : 2; /**< Where to align the snappable children horizontally*/
lv_scroll_snap_t scroll_snap_y : 2; /**< Where to align the snappable children vertically*/
//lv_dir_t scroll_dir : 4; /**< The allowed scroll direction(s)*/
lv_dir_t scroll_dir : 6;
uint8_t event_dsc_cnt : 6; /**< Number of event callbacks stored in `event_dsc` array*/
uint8_t layer_type : 2; /**< Cache the layer type here. Element of @lv_intermediate_layer_type_t */
} _lv_obj_spec_attr_t;
typedef struct _lv_obj_t {
const lv_obj_class_t * class_p;
struct _lv_obj_t * parent;
_lv_obj_spec_attr_t * spec_attr;
_lv_obj_style_t * styles;
#if LV_USE_USER_DATA
void * user_data;
#endif
lv_area_t coords;
lv_obj_flag_t flags;
lv_state_t state;
uint16_t layout_inv : 1;
uint16_t scr_layout_inv : 1;
uint16_t skip_trans : 1;
uint16_t style_cnt : 6;
uint16_t h_layout : 1;
uint16_t w_layout : 1;
} lv_obj_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize LVGL library.
* Should be called before any other LVGL related function.
*/
void lv_init(void);
#if LV_ENABLE_GC || !LV_MEM_CUSTOM
/**
* Deinit the 'lv' library
* Currently only implemented when not using custom allocators, or GC is enabled.
*/
void lv_deinit(void);
#endif
/**
* Returns whether the 'lv' library is currently initialized
*/
bool lv_is_initialized(void);
/**
* Create a base object (a rectangle)
* @param parent pointer to a parent object. If NULL then a screen will be created.
* @return pointer to the new object
*/
lv_obj_t * lv_obj_create(lv_obj_t * parent);
/*=====================
* Setter functions
*====================*/
/**
* Set one or more flags
* @param obj pointer to an object
* @param f R-ed values from `lv_obj_flag_t` to set.
*/
void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f);
/**
* Clear one or more flags
* @param obj pointer to an object
* @param f OR-ed values from `lv_obj_flag_t` to set.
*/
void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f);
/**
* Add one or more states to the object. The other state bits will remain unchanged.
* If specified in the styles, transition animation will be started from the previous state to the current.
* @param obj pointer to an object
* @param state the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED`
*/
void lv_obj_add_state(lv_obj_t * obj, lv_state_t state);
/**
* Remove one or more states to the object. The other state bits will remain unchanged.
* If specified in the styles, transition animation will be started from the previous state to the current.
* @param obj pointer to an object
* @param state the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED`
*/
void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state);
/**
* Set the user_data field of the object
* @param obj pointer to an object
* @param user_data pointer to the new user_data.
*/
#if LV_USE_USER_DATA
static inline void lv_obj_set_user_data(lv_obj_t * obj, void * user_data)
{
obj->user_data = user_data;
}
#endif
/*=======================
* Getter functions
*======================*/
/**
* Check if a given flag or all the given flags are set on an object.
* @param obj pointer to an object
* @param f the flag(s) to check (OR-ed values can be used)
* @return true: all flags are set; false: not all flags are set
*/
bool lv_obj_has_flag(const lv_obj_t * obj, lv_obj_flag_t f);
/**
* Check if a given flag or any of the flags are set on an object.
* @param obj pointer to an object
* @param f the flag(s) to check (OR-ed values can be used)
* @return true: at lest one flag flag is set; false: none of the flags are set
*/
bool lv_obj_has_flag_any(const lv_obj_t * obj, lv_obj_flag_t f);
/**
* Get the state of an object
* @param obj pointer to an object
* @return the state (OR-ed values from `lv_state_t`)
*/
lv_state_t lv_obj_get_state(const lv_obj_t * obj);
/**
* Check if the object is in a given state or not.
* @param obj pointer to an object
* @param state a state or combination of states to check
* @return true: `obj` is in `state`; false: `obj` is not in `state`
*/
bool lv_obj_has_state(const lv_obj_t * obj, lv_state_t state);
/**
* Get the group of the object
* @param obj pointer to an object
* @return the pointer to group of the object
*/
void * lv_obj_get_group(const lv_obj_t * obj);
/**
* Get the user_data field of the object
* @param obj pointer to an object
* @return the pointer to the user_data of the object
*/
#if LV_USE_USER_DATA
static inline void * lv_obj_get_user_data(lv_obj_t * obj)
{
return obj->user_data;
}
#endif
/*=======================
* Other functions
*======================*/
/**
* Allocate special data for an object if not allocated yet.
* @param obj pointer to an object
*/
void lv_obj_allocate_spec_attr(lv_obj_t * obj);
/**
* Check the type of obj.
* @param obj pointer to an object
* @param class_p a class to check (e.g. `lv_slider_class`)
* @return true: `class_p` is the `obj` class.
*/
bool lv_obj_check_type(const lv_obj_t * obj, const lv_obj_class_t * class_p);
/**
* Check if any object has a given class (type).
* It checks the ancestor classes too.
* @param obj pointer to an object
* @param class_p a class to check (e.g. `lv_slider_class`)
* @return true: `obj` has the given class
*/
bool lv_obj_has_class(const lv_obj_t * obj, const lv_obj_class_t * class_p);
/**
* Get the class (type) of the object
* @param obj pointer to an object
* @return the class (type) of the object
*/
const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj);
/**
* Check if any object is still "alive".
* @param obj pointer to an object
* @return true: valid
*/
bool lv_obj_is_valid(const lv_obj_t * obj);
/**
* Scale the given number of pixels (a distance or size) relative to a 160 DPI display
* considering the DPI of the `obj`'s display.
* It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the
* DPI of the display.
* @param obj an object whose display's dpi should be considered
* @param n the number of pixels to scale
* @return `n x current_dpi/160`
*/
static inline lv_coord_t lv_obj_dpx(const lv_obj_t * obj, lv_coord_t n)
{
return _LV_DPX_CALC(lv_disp_get_dpi(lv_obj_get_disp(obj)), n);
}
/**********************
* MACROS
**********************/
#if LV_USE_ASSERT_OBJ
# define LV_ASSERT_OBJ(obj_p, obj_class) \
do { \
LV_ASSERT_MSG(obj_p != NULL, "The object is NULL"); \
LV_ASSERT_MSG(lv_obj_has_class(obj_p, obj_class) == true, "Incompatible object type."); \
LV_ASSERT_MSG(lv_obj_is_valid(obj_p) == true, "The object is invalid, deleted or corrupted?"); \
} while(0)
# else
# define LV_ASSERT_OBJ(obj_p, obj_class) do{}while(0)
#endif
#if LV_USE_LOG && LV_LOG_TRACE_OBJ_CREATE
# define LV_TRACE_OBJ_CREATE(...) LV_LOG_TRACE(__VA_ARGS__)
#else
# define LV_TRACE_OBJ_CREATE(...)
#endif
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OBJ_H*/

View File

@ -0,0 +1,94 @@
/**
* @file lv_obj_class.h
*
*/
#ifndef LV_OBJ_CLASS_H
#define LV_OBJ_CLASS_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <stdint.h>
#include <stdbool.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct _lv_obj_t;
struct _lv_obj_class_t;
struct _lv_event_t;
typedef enum {
LV_OBJ_CLASS_EDITABLE_INHERIT, /**< Check the base class. Must have 0 value to let zero initialized class inherit*/
LV_OBJ_CLASS_EDITABLE_TRUE,
LV_OBJ_CLASS_EDITABLE_FALSE,
} lv_obj_class_editable_t;
typedef enum {
LV_OBJ_CLASS_GROUP_DEF_INHERIT, /**< Check the base class. Must have 0 value to let zero initialized class inherit*/
LV_OBJ_CLASS_GROUP_DEF_TRUE,
LV_OBJ_CLASS_GROUP_DEF_FALSE,
} lv_obj_class_group_def_t;
typedef void (*lv_obj_class_event_cb_t)(struct _lv_obj_class_t * class_p, struct _lv_event_t * e);
/**
* Describe the common methods of every object.
* Similar to a C++ class.
*/
typedef struct _lv_obj_class_t {
const struct _lv_obj_class_t * base_class;
void (*constructor_cb)(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * obj);
void (*destructor_cb)(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * obj);
#if LV_USE_USER_DATA
void * user_data;
#endif
void (*event_cb)(const struct _lv_obj_class_t * class_p,
struct _lv_event_t * e); /**< Widget type specific event function*/
lv_coord_t width_def;
lv_coord_t height_def;
uint32_t editable : 2; /**< Value from ::lv_obj_class_editable_t*/
uint32_t group_def : 2; /**< Value from ::lv_obj_class_group_def_t*/
uint32_t instance_size : 16;
} lv_obj_class_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Create an object form a class descriptor
* @param class_p pointer to a class
* @param parent pointer to an object where the new object should be created
* @return pointer to the created object
*/
struct _lv_obj_t * lv_obj_class_create_obj(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * parent);
void lv_obj_class_init_obj(struct _lv_obj_t * obj);
void _lv_obj_destruct(struct _lv_obj_t * obj);
bool lv_obj_is_editable(struct _lv_obj_t * obj);
bool lv_obj_is_group_def(struct _lv_obj_t * obj);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OBJ_CLASS_H*/

View File

@ -0,0 +1,172 @@
/**
* @file lv_obj_draw.h
*
*/
#ifndef LV_OBJ_DRAW_H
#define LV_OBJ_DRAW_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../draw/lv_draw.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct _lv_obj_t;
struct _lv_obj_class_t;
/** Cover check results.*/
typedef enum {
LV_COVER_RES_COVER = 0,
LV_COVER_RES_NOT_COVER = 1,
LV_COVER_RES_MASKED = 2,
} lv_cover_res_t;
typedef enum {
LV_LAYER_TYPE_NONE,
LV_LAYER_TYPE_SIMPLE,
LV_LAYER_TYPE_TRANSFORM,
} lv_layer_type_t;
typedef struct {
lv_draw_ctx_t * draw_ctx; /**< Draw context*/
const struct _lv_obj_class_t * class_p; /**< The class that sent the event */
uint32_t type; /**< The type if part being draw. Element of `lv_<name>_draw_part_type_t` */
lv_area_t * draw_area; /**< The area of the part being drawn*/
lv_draw_rect_dsc_t *
rect_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for rectangle-like parts*/
lv_draw_label_dsc_t *
label_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for text-like parts*/
lv_draw_line_dsc_t *
line_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for line-like parts*/
lv_draw_img_dsc_t *
img_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for image-like parts*/
lv_draw_arc_dsc_t *
arc_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for arc-like parts*/
const lv_point_t *
p1; /**< A point calculated during drawing. E.g. a point of chart or the center of an arc.*/
const lv_point_t * p2; /**< A point calculated during drawing. E.g. a point of chart.*/
char * text; /**< A text calculated during drawing. Can be modified. E.g. tick labels on a chart axis.*/
uint32_t text_length; /**< Size of the text buffer containing null-terminated text string calculated during drawing.*/
uint32_t part; /**< The current part for which the event is sent*/
uint32_t id; /**< The index of the part. E.g. a button's index on button matrix or table cell index.*/
lv_coord_t radius; /**< E.g. the radius of an arc (not the corner radius).*/
int32_t value; /**< A value calculated during drawing. E.g. Chart's tick line value.*/
const void * sub_part_ptr; /**< A pointer the identifies something in the part. E.g. chart series. */
} lv_obj_draw_part_dsc_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize a rectangle draw descriptor from an object's styles in its current state
* @param obj pointer to an object
* @param part part of the object, e.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc
* @param draw_dsc the descriptor to initialize.
* If an `..._opa` field is set to `LV_OPA_TRANSP` the related properties won't be initialized.
* Should be initialized with `lv_draw_rect_dsc_init(draw_dsc)`.
* @note Only the relevant fields will be set.
* E.g. if `border width == 0` the other border properties won't be evaluated.
*/
void lv_obj_init_draw_rect_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t * draw_dsc);
/**
* Initialize a label draw descriptor from an object's styles in its current state
* @param obj pointer to an object
* @param part part of the object, e.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc
* @param draw_dsc the descriptor to initialize.
* If the `opa` field is set to or the property is equal to `LV_OPA_TRANSP` the rest won't be initialized.
* Should be initialized with `lv_draw_label_dsc_init(draw_dsc)`.
*/
void lv_obj_init_draw_label_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc);
/**
* Initialize an image draw descriptor from an object's styles in its current state
* @param obj pointer to an object
* @param part part of the object, e.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc
* @param draw_dsc the descriptor to initialize.
* Should be initialized with `lv_draw_image_dsc_init(draw_dsc)`.
*/
void lv_obj_init_draw_img_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc);
/**
* Initialize a line draw descriptor from an object's styles in its current state
* @param obj pointer to an object
* @param part part of the object, e.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc
* @param draw_dsc the descriptor to initialize.
* Should be initialized with `lv_draw_line_dsc_init(draw_dsc)`.
*/
void lv_obj_init_draw_line_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc);
/**
* Initialize an arc draw descriptor from an object's styles in its current state
* @param obj pointer to an object
* @param part part of the object, e.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc
* @param draw_dsc the descriptor to initialize.
* Should be initialized with `lv_draw_arc_dsc_init(draw_dsc)`.
*/
void lv_obj_init_draw_arc_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc);
/**
* Get the required extra size (around the object's part) to draw shadow, outline, value etc.
* @param obj pointer to an object
* @param part part of the object
* @return the extra size required around the object
*/
lv_coord_t lv_obj_calculate_ext_draw_size(struct _lv_obj_t * obj, uint32_t part);
/**
* Initialize a draw descriptor used in events.
* @param dsc pointer to a descriptor. Later it should be passed as parameter to an `LV_EVENT_DRAW_PART_BEGIN/END` event.
* @param draw the current draw context. (usually returned by `lv_event_get_draw_ctx(e)`)
*/
void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, lv_draw_ctx_t * draw_ctx);
/**
* Check the type obj a part draw descriptor
* @param dsc the descriptor (normally the event parameter)
* @param class_p pointer to class to which `type` is related
* @param type element of `lv_<name>_draw_part_type_t`
* @return true if ::dsc is related to ::class_p and ::type
*/
bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const struct _lv_obj_class_t * class_p, uint32_t type);
/**
* Send a 'LV_EVENT_REFR_EXT_DRAW_SIZE' Call the ancestor's event handler to the object to refresh the value of the extended draw size.
* The result will be saved in `obj`.
* @param obj pointer to an object
*/
void lv_obj_refresh_ext_draw_size(struct _lv_obj_t * obj);
/**
* Get the extended draw area of an object.
* @param obj pointer to an object
* @return the size extended draw area around the real coordinates
*/
lv_coord_t _lv_obj_get_ext_draw_size(const struct _lv_obj_t * obj);
lv_layer_type_t _lv_obj_get_layer_type(const struct _lv_obj_t * obj);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OBJ_DRAW_H*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,449 @@
/**
* @file lv_obj_pos.h
*
*/
#ifndef LV_OBJ_POS_H
#define LV_OBJ_POS_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../misc/lv_area.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct _lv_obj_t;
typedef void (*lv_layout_update_cb_t)(struct _lv_obj_t *, void * user_data);
typedef struct {
lv_layout_update_cb_t cb;
void * user_data;
} lv_layout_dsc_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Set the position of an object relative to the set alignment.
* @param obj pointer to an object
* @param x new x coordinate
* @param y new y coordinate
* @note With default alignment it's the distance from the top left corner
* @note E.g. LV_ALIGN_CENTER alignment it's the offset from the center of the parent
* @note The position is interpreted on the content area of the parent
* @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)`
*/
void lv_obj_set_pos(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y);
/**
* Set the x coordinate of an object
* @param obj pointer to an object
* @param x new x coordinate
* @note With default alignment it's the distance from the top left corner
* @note E.g. LV_ALIGN_CENTER alignment it's the offset from the center of the parent
* @note The position is interpreted on the content area of the parent
* @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)`
*/
void lv_obj_set_x(struct _lv_obj_t * obj, lv_coord_t x);
/**
* Set the y coordinate of an object
* @param obj pointer to an object
* @param y new y coordinate
* @note With default alignment it's the distance from the top left corner
* @note E.g. LV_ALIGN_CENTER alignment it's the offset from the center of the parent
* @note The position is interpreted on the content area of the parent
* @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)`
*/
void lv_obj_set_y(struct _lv_obj_t * obj, lv_coord_t y);
/**
* Set the size of an object.
* @param obj pointer to an object
* @param w the new width
* @param h the new height
* @note possible values are:
* pixel simple set the size accordingly
* LV_SIZE_CONTENT set the size to involve all children in the given direction
* LV_SIZE_PCT(x) to set size in percentage of the parent's content area size (the size without paddings).
* x should be in [0..1000]% range
*/
void lv_obj_set_size(struct _lv_obj_t * obj, lv_coord_t w, lv_coord_t h);
/**
* Recalculate the size of the object
* @param obj pointer to an object
* @return true: the size has been changed
*/
bool lv_obj_refr_size(struct _lv_obj_t * obj);
/**
* Set the width of an object
* @param obj pointer to an object
* @param w the new width
* @note possible values are:
* pixel simple set the size accordingly
* LV_SIZE_CONTENT set the size to involve all children in the given direction
* lv_pct(x) to set size in percentage of the parent's content area size (the size without paddings).
* x should be in [0..1000]% range
*/
void lv_obj_set_width(struct _lv_obj_t * obj, lv_coord_t w);
/**
* Set the height of an object
* @param obj pointer to an object
* @param h the new height
* @note possible values are:
* pixel simple set the size accordingly
* LV_SIZE_CONTENT set the size to involve all children in the given direction
* lv_pct(x) to set size in percentage of the parent's content area size (the size without paddings).
* x should be in [0..1000]% range
*/
void lv_obj_set_height(struct _lv_obj_t * obj, lv_coord_t h);
/**
* Set the width reduced by the left and right padding and the border width.
* @param obj pointer to an object
* @param w the width without paddings in pixels
*/
void lv_obj_set_content_width(struct _lv_obj_t * obj, lv_coord_t w);
/**
* Set the height reduced by the top and bottom padding and the border width.
* @param obj pointer to an object
* @param h the height without paddings in pixels
*/
void lv_obj_set_content_height(struct _lv_obj_t * obj, lv_coord_t h);
/**
* Set a layout for an object
* @param obj pointer to an object
* @param layout pointer to a layout descriptor to set
*/
void lv_obj_set_layout(struct _lv_obj_t * obj, uint32_t layout);
/**
* Test whether the and object is positioned by a layout or not
* @param obj pointer to an object to test
* @return true: positioned by a layout; false: not positioned by a layout
*/
bool lv_obj_is_layout_positioned(const struct _lv_obj_t * obj);
/**
* Mark the object for layout update.
* @param obj pointer to an object whose children needs to be updated
*/
void lv_obj_mark_layout_as_dirty(struct _lv_obj_t * obj);
/**
* Update the layout of an object.
* @param obj pointer to an object whose children needs to be updated
*/
void lv_obj_update_layout(const struct _lv_obj_t * obj);
/**
* Register a new layout
* @param cb the layout update callback
* @param user_data custom data that will be passed to `cb`
* @return the ID of the new layout
*/
uint32_t lv_layout_register(lv_layout_update_cb_t cb, void * user_data);
/**
* Change the alignment of an object.
* @param obj pointer to an object to align
* @param align type of alignment (see 'lv_align_t' enum) `LV_ALIGN_OUT_...` can't be used.
*/
void lv_obj_set_align(struct _lv_obj_t * obj, lv_align_t align);
/**
* Change the alignment of an object and set new coordinates.
* Equivalent to:
* lv_obj_set_align(obj, align);
* lv_obj_set_pos(obj, x_ofs, y_ofs);
* @param obj pointer to an object to align
* @param align type of alignment (see 'lv_align_t' enum) `LV_ALIGN_OUT_...` can't be used.
* @param x_ofs x coordinate offset after alignment
* @param y_ofs y coordinate offset after alignment
*/
void lv_obj_align(struct _lv_obj_t * obj, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs);
/**
* Align an object to an other object.
* @param obj pointer to an object to align
* @param base pointer to an other object (if NULL `obj`s parent is used). 'obj' will be aligned to it.
* @param align type of alignment (see 'lv_align_t' enum)
* @param x_ofs x coordinate offset after alignment
* @param y_ofs y coordinate offset after alignment
* @note if the position or size of `base` changes `obj` needs to be aligned manually again
*/
void lv_obj_align_to(struct _lv_obj_t * obj, const struct _lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs,
lv_coord_t y_ofs);
/**
* Align an object to the center on its parent.
* @param obj pointer to an object to align
* @note if the parent size changes `obj` needs to be aligned manually again
*/
static inline void lv_obj_center(struct _lv_obj_t * obj)
{
lv_obj_align(obj, LV_ALIGN_CENTER, 0, 0);
}
/**
* Copy the coordinates of an object to an area
* @param obj pointer to an object
* @param coords pointer to an area to store the coordinates
*/
void lv_obj_get_coords(const struct _lv_obj_t * obj, lv_area_t * coords);
/**
* Get the x coordinate of object.
* @param obj pointer to an object
* @return distance of `obj` from the left side of its parent plus the parent's left padding
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
* call `lv_obj_update_layout(obj)`.
* @note Zero return value means the object is on the left padding of the parent, and not on the left edge.
* @note Scrolling of the parent doesn't change the returned value.
* @note The returned value is always the distance from the parent even if `obj` is positioned by a layout.
*/
lv_coord_t lv_obj_get_x(const struct _lv_obj_t * obj);
/**
* Get the x2 coordinate of object.
* @param obj pointer to an object
* @return distance of `obj` from the right side of its parent plus the parent's right padding
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
* call `lv_obj_update_layout(obj)`.
* @note Zero return value means the object is on the right padding of the parent, and not on the right edge.
* @note Scrolling of the parent doesn't change the returned value.
* @note The returned value is always the distance from the parent even if `obj` is positioned by a layout.
*/
lv_coord_t lv_obj_get_x2(const struct _lv_obj_t * obj);
/**
* Get the y coordinate of object.
* @param obj pointer to an object
* @return distance of `obj` from the top side of its parent plus the parent's top padding
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
* call `lv_obj_update_layout(obj)`.
* @note Zero return value means the object is on the top padding of the parent, and not on the top edge.
* @note Scrolling of the parent doesn't change the returned value.
* @note The returned value is always the distance from the parent even if `obj` is positioned by a layout.
*/
lv_coord_t lv_obj_get_y(const struct _lv_obj_t * obj);
/**
* Get the y2 coordinate of object.
* @param obj pointer to an object
* @return distance of `obj` from the bottom side of its parent plus the parent's bottom padding
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
* call `lv_obj_update_layout(obj)`.
* @note Zero return value means the object is on the bottom padding of the parent, and not on the bottom edge.
* @note Scrolling of the parent doesn't change the returned value.
* @note The returned value is always the distance from the parent even if `obj` is positioned by a layout.
*/
lv_coord_t lv_obj_get_y2(const struct _lv_obj_t * obj);
/**
* Get the actually set x coordinate of object, i.e. the offset form the set alignment
* @param obj pointer to an object
* @return the set x coordinate
*/
lv_coord_t lv_obj_get_x_aligned(const struct _lv_obj_t * obj);
/**
* Get the actually set y coordinate of object, i.e. the offset form the set alignment
* @param obj pointer to an object
* @return the set y coordinate
*/
lv_coord_t lv_obj_get_y_aligned(const struct _lv_obj_t * obj);
/**
* Get the width of an object
* @param obj pointer to an object
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
* call `lv_obj_update_layout(obj)`.
* @return the width in pixels
*/
lv_coord_t lv_obj_get_width(const struct _lv_obj_t * obj);
/**
* Get the height of an object
* @param obj pointer to an object
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
* call `lv_obj_update_layout(obj)`.
* @return the height in pixels
*/
lv_coord_t lv_obj_get_height(const struct _lv_obj_t * obj);
/**
* Get the width reduced by the left and right padding and the border width.
* @param obj pointer to an object
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
* call `lv_obj_update_layout(obj)`.
* @return the width which still fits into its parent without causing overflow (making the parent scrollable)
*/
lv_coord_t lv_obj_get_content_width(const struct _lv_obj_t * obj);
/**
* Get the height reduced by the top and bottom padding and the border width.
* @param obj pointer to an object
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
* call `lv_obj_update_layout(obj)`.
* @return the height which still fits into the parent without causing overflow (making the parent scrollable)
*/
lv_coord_t lv_obj_get_content_height(const struct _lv_obj_t * obj);
/**
* Get the area reduced by the paddings and the border width.
* @param obj pointer to an object
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
* call `lv_obj_update_layout(obj)`.
* @param area the area which still fits into the parent without causing overflow (making the parent scrollable)
*/
void lv_obj_get_content_coords(const struct _lv_obj_t * obj, lv_area_t * area);
/**
* Get the width occupied by the "parts" of the widget. E.g. the width of all columns of a table.
* @param obj pointer to an objects
* @return the width of the virtually drawn content
* @note This size independent from the real size of the widget.
* It just tells how large the internal ("virtual") content is.
*/
lv_coord_t lv_obj_get_self_width(const struct _lv_obj_t * obj);
/**
* Get the height occupied by the "parts" of the widget. E.g. the height of all rows of a table.
* @param obj pointer to an objects
* @return the width of the virtually drawn content
* @note This size independent from the real size of the widget.
* It just tells how large the internal ("virtual") content is.
*/
lv_coord_t lv_obj_get_self_height(const struct _lv_obj_t * obj);
/**
* Handle if the size of the internal ("virtual") content of an object has changed.
* @param obj pointer to an object
* @return false: nothing happened; true: refresh happened
*/
bool lv_obj_refresh_self_size(struct _lv_obj_t * obj);
void lv_obj_refr_pos(struct _lv_obj_t * obj);
void lv_obj_move_to(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y);
void lv_obj_move_children_by(struct _lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_diff, bool ignore_floating);
/**
* Transform a point using the angle and zoom style properties of an object
* @param obj pointer to an object whose style properties should be used
* @param p a point to transform, the result will be written back here too
* @param recursive consider the transformation properties of the parents too
* @param inv do the inverse of the transformation (-angle and 1/zoom)
*/
void lv_obj_transform_point(const struct _lv_obj_t * obj, lv_point_t * p, bool recursive, bool inv);
/**
* Transform an area using the angle and zoom style properties of an object
* @param obj pointer to an object whose style properties should be used
* @param area an area to transform, the result will be written back here too
* @param recursive consider the transformation properties of the parents too
* @param inv do the inverse of the transformation (-angle and 1/zoom)
*/
void lv_obj_get_transformed_area(const struct _lv_obj_t * obj, lv_area_t * area, bool recursive, bool inv);
/**
* Mark an area of an object as invalid.
* The area will be truncated to the object's area and marked for redraw.
* @param obj pointer to an object
* @param area the area to redraw
*/
void lv_obj_invalidate_area(const struct _lv_obj_t * obj, const lv_area_t * area);
/**
* Mark the object as invalid to redrawn its area
* @param obj pointer to an object
*/
void lv_obj_invalidate(const struct _lv_obj_t * obj);
/**
* Tell whether an area of an object is visible (even partially) now or not
* @param obj pointer to an object
* @param area the are to check. The visible part of the area will be written back here.
* @return true visible; false not visible (hidden, out of parent, on other screen, etc)
*/
bool lv_obj_area_is_visible(const struct _lv_obj_t * obj, lv_area_t * area);
/**
* Tell whether an object is visible (even partially) now or not
* @param obj pointer to an object
* @return true: visible; false not visible (hidden, out of parent, on other screen, etc)
*/
bool lv_obj_is_visible(const struct _lv_obj_t * obj);
/**
* Set the size of an extended clickable area
* @param obj pointer to an object
* @param size extended clickable area in all 4 directions [px]
*/
void lv_obj_set_ext_click_area(struct _lv_obj_t * obj, lv_coord_t size);
/**
* Get the an area where to object can be clicked.
* It's the object's normal area plus the extended click area.
* @param obj pointer to an object
* @param area store the result area here
*/
void lv_obj_get_click_area(const struct _lv_obj_t * obj, lv_area_t * area);
/**
* Hit-test an object given a particular point in screen space.
* @param obj object to hit-test
* @param point screen-space point (absolute coordinate)
* @return true: if the object is considered under the point
*/
bool lv_obj_hit_test(struct _lv_obj_t * obj, const lv_point_t * point);
/**
* Clamp a width between min and max width. If the min/max width is in percentage value use the ref_width
* @param width width to clamp
* @param min_width the minimal width
* @param max_width the maximal width
* @param ref_width the reference width used when min/max width is in percentage
* @return the clamped width
*/
lv_coord_t lv_clamp_width(lv_coord_t width, lv_coord_t min_width, lv_coord_t max_width, lv_coord_t ref_width);
/**
* Clamp a height between min and max height. If the min/max height is in percentage value use the ref_height
* @param height height to clamp
* @param min_height the minimal height
* @param max_height the maximal height
* @param ref_height the reference height used when min/max height is in percentage
* @return the clamped height
*/
lv_coord_t lv_clamp_height(lv_coord_t height, lv_coord_t min_height, lv_coord_t max_height, lv_coord_t ref_height);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OBJ_POS_H*/

View File

@ -0,0 +1,329 @@
/**
* @file lv_obj_scroll.h
*
*/
#ifndef LV_OBJ_SCROLL_H
#define LV_OBJ_SCROLL_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../misc/lv_area.h"
#include "../misc/lv_anim.h"
#include "../misc/lv_types.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/*Can't include lv_obj.h because it includes this header file*/
struct _lv_obj_t;
/** Scrollbar modes: shows when should the scrollbars be visible*/
enum {
LV_SCROLLBAR_MODE_OFF, /**< Never show scrollbars*/
LV_SCROLLBAR_MODE_ON, /**< Always show scrollbars*/
LV_SCROLLBAR_MODE_ACTIVE, /**< Show scroll bars when object is being scrolled*/
LV_SCROLLBAR_MODE_AUTO, /**< Show scroll bars when the content is large enough to be scrolled*/
};
typedef uint8_t lv_scrollbar_mode_t;
/** Scroll span align options. Tells where to align the snappable children when scroll stops.*/
enum {
LV_SCROLL_SNAP_NONE, /**< Do not align, leave where it is*/
LV_SCROLL_SNAP_START, /**< Align to the left/top*/
LV_SCROLL_SNAP_END, /**< Align to the right/bottom*/
LV_SCROLL_SNAP_CENTER /**< Align to the center*/
};
typedef uint8_t lv_scroll_snap_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/*=====================
* Setter functions
*====================*/
/**
* Set how the scrollbars should behave.
* @param obj pointer to an object
* @param mode LV_SCROLL_MODE_ON/OFF/AUTO/ACTIVE
*/
void lv_obj_set_scrollbar_mode(struct _lv_obj_t * obj, lv_scrollbar_mode_t mode);
/**
* Set the object in which directions can be scrolled
* @param obj pointer to an object
* @param dir the allow scroll directions. An element or OR-ed values of `lv_dir_t`
*/
void lv_obj_set_scroll_dir(struct _lv_obj_t * obj, lv_dir_t dir);
/**
* Set where to snap the children when scrolling ends horizontally
* @param obj pointer to an object
* @param align the snap align to set from `lv_scroll_snap_t`
*/
void lv_obj_set_scroll_snap_x(struct _lv_obj_t * obj, lv_scroll_snap_t align);
/**
* Set where to snap the children when scrolling ends vertically
* @param obj pointer to an object
* @param align the snap align to set from `lv_scroll_snap_t`
*/
void lv_obj_set_scroll_snap_y(struct _lv_obj_t * obj, lv_scroll_snap_t align);
/*=====================
* Getter functions
*====================*/
/**
* Get the current scroll mode (when to hide the scrollbars)
* @param obj pointer to an object
* @return the current scroll mode from `lv_scrollbar_mode_t`
*/
lv_scrollbar_mode_t lv_obj_get_scrollbar_mode(const struct _lv_obj_t * obj);
/**
* Get the object in which directions can be scrolled
* @param obj pointer to an object
* @param dir the allow scroll directions. An element or OR-ed values of `lv_dir_t`
*/
lv_dir_t lv_obj_get_scroll_dir(const struct _lv_obj_t * obj);
/**
* Get where to snap the children when scrolling ends horizontally
* @param obj pointer to an object
* @return the current snap align from `lv_scroll_snap_t`
*/
lv_scroll_snap_t lv_obj_get_scroll_snap_x(const struct _lv_obj_t * obj);
/**
* Get where to snap the children when scrolling ends vertically
* @param obj pointer to an object
* @return the current snap align from `lv_scroll_snap_t`
*/
lv_scroll_snap_t lv_obj_get_scroll_snap_y(const struct _lv_obj_t * obj);
/**
* Get current X scroll position.
* @param obj pointer to an object
* @return the current scroll position from the left edge.
* If the object is not scrolled return 0
* If scrolled return > 0
* If scrolled in (elastic scroll) return < 0
*/
lv_coord_t lv_obj_get_scroll_x(const struct _lv_obj_t * obj);
/**
* Get current Y scroll position.
* @param obj pointer to an object
* @return the current scroll position from the top edge.
* If the object is not scrolled return 0
* If scrolled return > 0
* If scrolled inside return < 0
*/
lv_coord_t lv_obj_get_scroll_y(const struct _lv_obj_t * obj);
/**
* Return the height of the area above the object.
* That is the number of pixels the object can be scrolled down.
* Normally positive but can be negative when scrolled inside.
* @param obj pointer to an object
* @return the scrollable area above the object in pixels
*/
lv_coord_t lv_obj_get_scroll_top(struct _lv_obj_t * obj);
/**
* Return the height of the area below the object.
* That is the number of pixels the object can be scrolled down.
* Normally positive but can be negative when scrolled inside.
* @param obj pointer to an object
* @return the scrollable area below the object in pixels
*/
lv_coord_t lv_obj_get_scroll_bottom(struct _lv_obj_t * obj);
/**
* Return the width of the area on the left the object.
* That is the number of pixels the object can be scrolled down.
* Normally positive but can be negative when scrolled inside.
* @param obj pointer to an object
* @return the scrollable area on the left the object in pixels
*/
lv_coord_t lv_obj_get_scroll_left(struct _lv_obj_t * obj);
/**
* Return the width of the area on the right the object.
* That is the number of pixels the object can be scrolled down.
* Normally positive but can be negative when scrolled inside.
* @param obj pointer to an object
* @return the scrollable area on the right the object in pixels
*/
lv_coord_t lv_obj_get_scroll_right(struct _lv_obj_t * obj);
/**
* Get the X and Y coordinates where the scrolling will end for this object if a scrolling animation is in progress.
* If no scrolling animation, give the current `x` or `y` scroll position.
* @param obj pointer to an object
* @param end pointer to store the result
*/
void lv_obj_get_scroll_end(struct _lv_obj_t * obj, lv_point_t * end);
/*=====================
* Other functions
*====================*/
/**
* Scroll by a given amount of pixels
* @param obj pointer to an object to scroll
* @param dx pixels to scroll horizontally
* @param dy pixels to scroll vertically
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
* @note > 0 value means scroll right/bottom (show the more content on the right/bottom)
* @note e.g. dy = -20 means scroll down 20 px
*/
void lv_obj_scroll_by(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en);
/**
* Scroll by a given amount of pixels.
* `dx` and `dy` will be limited internally to allow scrolling only on the content area.
* @param obj pointer to an object to scroll
* @param dx pixels to scroll horizontally
* @param dy pixels to scroll vertically
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
* @note e.g. dy = -20 means scroll down 20 px
*/
void lv_obj_scroll_by_bounded(struct _lv_obj_t * obj, lv_coord_t dx, lv_coord_t dy, lv_anim_enable_t anim_en);
/**
* Scroll to a given coordinate on an object.
* `x` and `y` will be limited internally to allow scrolling only on the content area.
* @param obj pointer to an object to scroll
* @param x pixels to scroll horizontally
* @param y pixels to scroll vertically
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
*/
void lv_obj_scroll_to(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en);
/**
* Scroll to a given X coordinate on an object.
* `x` will be limited internally to allow scrolling only on the content area.
* @param obj pointer to an object to scroll
* @param x pixels to scroll horizontally
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
*/
void lv_obj_scroll_to_x(struct _lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en);
/**
* Scroll to a given Y coordinate on an object
* `y` will be limited internally to allow scrolling only on the content area.
* @param obj pointer to an object to scroll
* @param y pixels to scroll vertically
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
*/
void lv_obj_scroll_to_y(struct _lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en);
/**
* Scroll to an object until it becomes visible on its parent
* @param obj pointer to an object to scroll into view
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
*/
void lv_obj_scroll_to_view(struct _lv_obj_t * obj, lv_anim_enable_t anim_en);
/**
* Scroll to an object until it becomes visible on its parent.
* Do the same on the parent's parent, and so on.
* Therefore the object will be scrolled into view even it has nested scrollable parents
* @param obj pointer to an object to scroll into view
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
*/
void lv_obj_scroll_to_view_recursive(struct _lv_obj_t * obj, lv_anim_enable_t anim_en);
/**
* Low level function to scroll by given x and y coordinates.
* `LV_EVENT_SCROLL` is sent.
* @param obj pointer to an object to scroll
* @param x pixels to scroll horizontally
* @param y pixels to scroll vertically
* @return `LV_RES_INV`: to object was deleted in `LV_EVENT_SCROLL`;
* `LV_RES_OK`: if the object is still valid
*/
lv_res_t _lv_obj_scroll_by_raw(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y);
/**
* Tell whether an object is being scrolled or not at this moment
* @param obj pointer to an object
* @return true: `obj` is being scrolled
*/
bool lv_obj_is_scrolling(const struct _lv_obj_t * obj);
/**
* Check the children of `obj` and scroll `obj` to fulfill the scroll_snap settings
* @param obj an object whose children needs to checked and snapped
* @param anim_en LV_ANIM_ON/OFF
*/
void lv_obj_update_snap(struct _lv_obj_t * obj, lv_anim_enable_t anim_en);
/**
* Get the area of the scrollbars
* @param obj pointer to an object
* @param hor pointer to store the area of the horizontal scrollbar
* @param ver pointer to store the area of the vertical scrollbar
*/
void lv_obj_get_scrollbar_area(struct _lv_obj_t * obj, lv_area_t * hor, lv_area_t * ver);
/**
* Invalidate the area of the scrollbars
* @param obj pointer to an object
*/
void lv_obj_scrollbar_invalidate(struct _lv_obj_t * obj);
/**
* Checked if the content is scrolled "in" and adjusts it to a normal position.
* @param obj pointer to an object
* @param anim_en LV_ANIM_ON/OFF
*/
void lv_obj_readjust_scroll(struct _lv_obj_t * obj, lv_anim_enable_t anim_en);
/**
* Return the maxist time of scroll with animation
* @param min the minimum time
* @param max the maximum time
*/
void lv_obj_set_scroll_anim_time(lv_coord_t min,lv_coord_t max);
/**
* Return the minimum time of scroll with animation
* @return
*/
lv_coord_t lv_obj_scroll_anim_time_min(void);
/**
* Return the maximum time of scroll with animation
* @return
*/
lv_coord_t lv_obj_scroll_anim_time_max(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OBJ_SCROLL_H*/

View File

@ -0,0 +1,248 @@
/**
* @file lv_obj_style.h
*
*/
#ifndef LV_OBJ_STYLE_H
#define LV_OBJ_STYLE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <stdint.h>
#include <stdbool.h>
#include "../misc/lv_bidi.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/*Can't include lv_obj.h because it includes this header file*/
struct _lv_obj_t;
typedef enum {
_LV_STYLE_STATE_CMP_SAME, /*The style properties in the 2 states are identical*/
_LV_STYLE_STATE_CMP_DIFF_REDRAW, /*The differences can be shown with a simple redraw*/
_LV_STYLE_STATE_CMP_DIFF_DRAW_PAD, /*The differences can be shown with a simple redraw*/
_LV_STYLE_STATE_CMP_DIFF_LAYOUT, /*The differences can be shown with a simple redraw*/
} _lv_style_state_cmp_t;
typedef uint32_t lv_style_selector_t;
typedef struct {
lv_style_t * style;
uint32_t selector : 24;
uint32_t is_local : 1;
uint32_t is_trans : 1;
} _lv_obj_style_t;
typedef struct {
uint16_t time;
uint16_t delay;
lv_style_selector_t selector;
lv_style_prop_t prop;
lv_anim_path_cb_t path_cb;
#if LV_USE_USER_DATA
void * user_data;
#endif
} _lv_obj_style_transition_dsc_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize the object related style manager module.
* Called by LVGL in `lv_init()`
*/
void _lv_obj_style_init(void);
/**
* Add a style to an object.
* @param obj pointer to an object
* @param style pointer to a style to add
* @param selector OR-ed value of parts and state to which the style should be added
* @example lv_obj_add_style(btn, &style_btn, 0); //Default button style
* @example lv_obj_add_style(btn, &btn_red, LV_STATE_PRESSED); //Overwrite only some colors to red when pressed
*/
void lv_obj_add_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector);
/**
* Add a style to an object.
* @param obj pointer to an object
* @param style pointer to a style to remove. Can be NULL to check only the selector
* @param selector OR-ed values of states and a part to remove only styles with matching selectors. LV_STATE_ANY and LV_PART_ANY can be used
* @example lv_obj_remove_style(obj, &style, LV_PART_ANY | LV_STATE_ANY); //Remove a specific style
* @example lv_obj_remove_style(obj, NULL, LV_PART_MAIN | LV_STATE_ANY); //Remove all styles from the main part
* @example lv_obj_remove_style(obj, NULL, LV_PART_ANY | LV_STATE_ANY); //Remove all styles
*/
void lv_obj_remove_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector);
/**
* Remove all styles from an object
* @param obj pointer to an object
*/
static inline void lv_obj_remove_style_all(struct _lv_obj_t * obj)
{
lv_obj_remove_style(obj, NULL, LV_PART_ANY | LV_STATE_ANY);
}
/**
* Notify all object if a style is modified
* @param style pointer to a style. Only the objects with this style will be notified
* (NULL to notify all objects)
*/
void lv_obj_report_style_change(lv_style_t * style);
/**
* Notify an object and its children about its style is modified.
* @param obj pointer to an object
* @param part the part whose style was changed. E.g. `LV_PART_ANY`, `LV_PART_MAIN`
* @param prop `LV_STYLE_PROP_ANY` or an `LV_STYLE_...` property.
* It is used to optimize what needs to be refreshed.
* `LV_STYLE_PROP_INV` to perform only a style cache update
*/
void lv_obj_refresh_style(struct _lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop);
/**
* Enable or disable automatic style refreshing when a new style is added/removed to/from an object
* or any other style change happens.
* @param en true: enable refreshing; false: disable refreshing
*/
void lv_obj_enable_style_refresh(bool en);
/**
* Get the value of a style property. The current state of the object will be considered.
* Inherited properties will be inherited.
* If a property is not set a default value will be returned.
* @param obj pointer to an object
* @param part a part from which the property should be get
* @param prop the property to get
* @return the value of the property.
* Should be read from the correct field of the `lv_style_value_t` according to the type of the property.
*/
lv_style_value_t lv_obj_get_style_prop(const struct _lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop);
/**
* Set local style property on an object's part and state.
* @param obj pointer to an object
* @param prop the property
* @param value value of the property. The correct element should be set according to the type of the property
* @param selector OR-ed value of parts and state for which the style should be set
*/
void lv_obj_set_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value,
lv_style_selector_t selector);
void lv_obj_set_local_style_prop_meta(struct _lv_obj_t * obj, lv_style_prop_t prop, uint16_t meta,
lv_style_selector_t selector);
lv_style_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value,
lv_style_selector_t selector);
/**
* Remove a local style property from a part of an object with a given state.
* @param obj pointer to an object
* @param prop a style property to remove.
* @param selector OR-ed value of parts and state for which the style should be removed
* @return true the property was found and removed; false: the property was not found
*/
bool lv_obj_remove_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector);
/**
* Used internally for color filtering
*/
lv_style_value_t _lv_obj_style_apply_color_filter(const struct _lv_obj_t * obj, uint32_t part, lv_style_value_t v);
/**
* Used internally to create a style transition
* @param obj
* @param part
* @param prev_state
* @param new_state
* @param tr
*/
void _lv_obj_style_create_transition(struct _lv_obj_t * obj, lv_part_t part, lv_state_t prev_state,
lv_state_t new_state, const _lv_obj_style_transition_dsc_t * tr);
/**
* Used internally to compare the appearance of an object in 2 states
* @param obj
* @param state1
* @param state2
* @return
*/
_lv_style_state_cmp_t _lv_obj_style_state_compare(struct _lv_obj_t * obj, lv_state_t state1, lv_state_t state2);
/**
* Fade in an an object and all its children.
* @param obj the object to fade in
* @param time time of fade
* @param delay delay to start the animation
*/
void lv_obj_fade_in(struct _lv_obj_t * obj, uint32_t time, uint32_t delay);
/**
* Fade out an an object and all its children.
* @param obj the object to fade out
* @param time time of fade
* @param delay delay to start the animation
*/
void lv_obj_fade_out(struct _lv_obj_t * obj, uint32_t time, uint32_t delay);
lv_state_t lv_obj_style_get_selector_state(lv_style_selector_t selector);
lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector);
#include "lv_obj_style_gen.h"
static inline void lv_obj_set_style_pad_all(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
{
lv_obj_set_style_pad_left(obj, value, selector);
lv_obj_set_style_pad_right(obj, value, selector);
lv_obj_set_style_pad_top(obj, value, selector);
lv_obj_set_style_pad_bottom(obj, value, selector);
}
static inline void lv_obj_set_style_pad_hor(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
{
lv_obj_set_style_pad_left(obj, value, selector);
lv_obj_set_style_pad_right(obj, value, selector);
}
static inline void lv_obj_set_style_pad_ver(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
{
lv_obj_set_style_pad_top(obj, value, selector);
lv_obj_set_style_pad_bottom(obj, value, selector);
}
static inline void lv_obj_set_style_pad_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
{
lv_obj_set_style_pad_row(obj, value, selector);
lv_obj_set_style_pad_column(obj, value, selector);
}
static inline void lv_obj_set_style_size(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
{
lv_obj_set_style_width(obj, value, selector);
lv_obj_set_style_height(obj, value, selector);
}
lv_text_align_t lv_obj_calculate_style_text_align(const struct _lv_obj_t * obj, lv_part_t part, const char * txt);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OBJ_STYLE_H*/

View File

@ -0,0 +1,648 @@
static inline lv_coord_t lv_obj_get_style_width(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_WIDTH);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_min_width(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MIN_WIDTH);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_max_width(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MAX_WIDTH);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_height(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_HEIGHT);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_min_height(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MIN_HEIGHT);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_max_height(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MAX_HEIGHT);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_x(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_X);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_y(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_Y);
return (lv_coord_t)v.num;
}
static inline lv_align_t lv_obj_get_style_align(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ALIGN);
return (lv_align_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_transform_width(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_WIDTH);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_transform_height(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_HEIGHT);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_translate_x(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSLATE_X);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_translate_y(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSLATE_Y);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_transform_zoom(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_ZOOM);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_transform_angle(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_ANGLE);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_transform_pivot_x(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_PIVOT_X);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_transform_pivot_y(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_PIVOT_Y);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_pad_top(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_TOP);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_pad_bottom(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_BOTTOM);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_pad_left(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_LEFT);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_pad_right(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_RIGHT);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_pad_row(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_ROW);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_pad_column(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_COLUMN);
return (lv_coord_t)v.num;
}
static inline lv_color_t lv_obj_get_style_bg_color(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_bg_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_bg_opa(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_OPA);
return (lv_opa_t)v.num;
}
static inline lv_color_t lv_obj_get_style_bg_grad_color(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_bg_grad_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR));
return v.color;
}
static inline lv_grad_dir_t lv_obj_get_style_bg_grad_dir(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_DIR);
return (lv_grad_dir_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_bg_main_stop(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_MAIN_STOP);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_bg_grad_stop(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_STOP);
return (lv_coord_t)v.num;
}
static inline const lv_grad_dsc_t * lv_obj_get_style_bg_grad(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD);
return (const lv_grad_dsc_t *)v.ptr;
}
static inline lv_dither_mode_t lv_obj_get_style_bg_dither_mode(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_DITHER_MODE);
return (lv_dither_mode_t)v.num;
}
static inline const void * lv_obj_get_style_bg_img_src(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_SRC);
return (const void *)v.ptr;
}
static inline lv_opa_t lv_obj_get_style_bg_img_opa(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_OPA);
return (lv_opa_t)v.num;
}
static inline lv_color_t lv_obj_get_style_bg_img_recolor(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_bg_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_bg_img_recolor_opa(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR_OPA);
return (lv_opa_t)v.num;
}
static inline bool lv_obj_get_style_bg_img_tiled(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_TILED);
return (bool)v.num;
}
static inline lv_color_t lv_obj_get_style_border_color(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_border_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_border_opa(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_OPA);
return (lv_opa_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_border_width(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_WIDTH);
return (lv_coord_t)v.num;
}
static inline lv_border_side_t lv_obj_get_style_border_side(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_SIDE);
return (lv_border_side_t)v.num;
}
static inline bool lv_obj_get_style_border_post(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_POST);
return (bool)v.num;
}
static inline lv_coord_t lv_obj_get_style_outline_width(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_WIDTH);
return (lv_coord_t)v.num;
}
static inline lv_color_t lv_obj_get_style_outline_color(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_outline_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_outline_opa(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_OPA);
return (lv_opa_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_outline_pad(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_PAD);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_shadow_width(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_WIDTH);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_shadow_ofs_x(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OFS_X);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_shadow_ofs_y(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OFS_Y);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_shadow_spread(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_SPREAD);
return (lv_coord_t)v.num;
}
static inline lv_color_t lv_obj_get_style_shadow_color(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_shadow_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_shadow_opa(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OPA);
return (lv_opa_t)v.num;
}
static inline lv_opa_t lv_obj_get_style_img_opa(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_OPA);
return (lv_opa_t)v.num;
}
static inline lv_color_t lv_obj_get_style_img_recolor(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_img_recolor_opa(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR_OPA);
return (lv_opa_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_line_width(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_WIDTH);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_line_dash_width(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_DASH_WIDTH);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_line_dash_gap(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_DASH_GAP);
return (lv_coord_t)v.num;
}
static inline bool lv_obj_get_style_line_rounded(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_ROUNDED);
return (bool)v.num;
}
static inline lv_color_t lv_obj_get_style_line_color(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_line_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_COLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_line_opa(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_OPA);
return (lv_opa_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_arc_width(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_WIDTH);
return (lv_coord_t)v.num;
}
static inline bool lv_obj_get_style_arc_rounded(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_ROUNDED);
return (bool)v.num;
}
static inline lv_color_t lv_obj_get_style_arc_color(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_arc_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_COLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_arc_opa(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_OPA);
return (lv_opa_t)v.num;
}
static inline const void * lv_obj_get_style_arc_img_src(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_IMG_SRC);
return (const void *)v.ptr;
}
static inline lv_color_t lv_obj_get_style_text_color(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_text_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_COLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_text_opa(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_OPA);
return (lv_opa_t)v.num;
}
static inline const lv_font_t * lv_obj_get_style_text_font(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_FONT);
return (const lv_font_t *)v.ptr;
}
static inline lv_coord_t lv_obj_get_style_text_letter_space(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_LETTER_SPACE);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_text_line_space(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_LINE_SPACE);
return (lv_coord_t)v.num;
}
static inline lv_text_decor_t lv_obj_get_style_text_decor(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_DECOR);
return (lv_text_decor_t)v.num;
}
static inline lv_text_align_t lv_obj_get_style_text_align(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_ALIGN);
return (lv_text_align_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_radius(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_RADIUS);
return (lv_coord_t)v.num;
}
static inline bool lv_obj_get_style_clip_corner(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_CLIP_CORNER);
return (bool)v.num;
}
static inline lv_opa_t lv_obj_get_style_opa(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OPA);
return (lv_opa_t)v.num;
}
static inline const lv_color_filter_dsc_t * lv_obj_get_style_color_filter_dsc(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_COLOR_FILTER_DSC);
return (const lv_color_filter_dsc_t *)v.ptr;
}
static inline lv_opa_t lv_obj_get_style_color_filter_opa(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_COLOR_FILTER_OPA);
return (lv_opa_t)v.num;
}
static inline const lv_anim_t * lv_obj_get_style_anim(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM);
return (const lv_anim_t *)v.ptr;
}
static inline uint32_t lv_obj_get_style_anim_time(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM_TIME);
return (uint32_t)v.num;
}
static inline uint32_t lv_obj_get_style_anim_speed(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM_SPEED);
return (uint32_t)v.num;
}
static inline const lv_style_transition_dsc_t * lv_obj_get_style_transition(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSITION);
return (const lv_style_transition_dsc_t *)v.ptr;
}
static inline lv_blend_mode_t lv_obj_get_style_blend_mode(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BLEND_MODE);
return (lv_blend_mode_t)v.num;
}
static inline uint16_t lv_obj_get_style_layout(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LAYOUT);
return (uint16_t)v.num;
}
static inline lv_base_dir_t lv_obj_get_style_base_dir(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BASE_DIR);
return (lv_base_dir_t)v.num;
}
void lv_obj_set_style_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_min_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_max_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_min_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_max_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_align(struct _lv_obj_t * obj, lv_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_translate_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_translate_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_zoom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_angle(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_pivot_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_pivot_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_pad_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_pad_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_pad_left(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_pad_right(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_pad_row(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_grad_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_grad_dir(struct _lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_main_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_grad_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_grad(struct _lv_obj_t * obj, const lv_grad_dsc_t * value, lv_style_selector_t selector);
void lv_obj_set_style_bg_dither_mode(struct _lv_obj_t * obj, lv_dither_mode_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector);
void lv_obj_set_style_bg_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_img_tiled(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
void lv_obj_set_style_border_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_border_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_border_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_border_side(struct _lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector);
void lv_obj_set_style_border_post(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
void lv_obj_set_style_outline_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_outline_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_outline_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_outline_pad(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_shadow_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_shadow_ofs_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_shadow_ofs_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_shadow_spread(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_shadow_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_arc_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector);
void lv_obj_set_style_text_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_font(struct _lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector);
void lv_obj_set_style_text_letter_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_line_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_decor(struct _lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_align(struct _lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_radius(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_clip_corner(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector);
void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_anim(struct _lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector);
void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector);
void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector);
void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector);
void lv_obj_set_style_blend_mode(struct _lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector);
void lv_obj_set_style_layout(struct _lv_obj_t * obj, uint16_t value, lv_style_selector_t selector);
void lv_obj_set_style_base_dir(struct _lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector);

View File

@ -0,0 +1,172 @@
/**
* @file struct _lv_obj_tree.h
*
*/
#ifndef LV_OBJ_TREE_H
#define LV_OBJ_TREE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <stddef.h>
#include <stdbool.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct _lv_obj_t;
struct _lv_obj_class_t;
typedef enum {
LV_OBJ_TREE_WALK_NEXT,
LV_OBJ_TREE_WALK_SKIP_CHILDREN,
LV_OBJ_TREE_WALK_END,
} lv_obj_tree_walk_res_t;
typedef lv_obj_tree_walk_res_t (*lv_obj_tree_walk_cb_t)(struct _lv_obj_t *, void *);
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Delete an object and all of its children.
* Also remove the objects from their group and remove all animations (if any).
* Send `LV_EVENT_DELETED` to deleted objects.
* @param obj pointer to an object
*/
void lv_obj_del(struct _lv_obj_t * obj);
/**
* Delete all children of an object.
* Also remove the objects from their group and remove all animations (if any).
* Send `LV_EVENT_DELETED` to deleted objects.
* @param obj pointer to an object
*/
void lv_obj_clean(struct _lv_obj_t * obj);
/**
* Delete an object after some delay
* @param obj pointer to an object
* @param delay_ms time to wait before delete in milliseconds
*/
void lv_obj_del_delayed(struct _lv_obj_t * obj, uint32_t delay_ms);
/**
* A function to be easily used in animation ready callback to delete an object when the animation is ready
* @param a pointer to the animation
*/
void lv_obj_del_anim_ready_cb(lv_anim_t * a);
/**
* Helper function for asynchronously deleting objects.
* Useful for cases where you can't delete an object directly in an `LV_EVENT_DELETE` handler (i.e. parent).
* @param obj object to delete
* @see lv_async_call
*/
void lv_obj_del_async(struct _lv_obj_t * obj);
/**
* Move the parent of an object. The relative coordinates will be kept.
*
* @param obj pointer to an object whose parent needs to be changed
* @param parent pointer to the new parent
*/
void lv_obj_set_parent(struct _lv_obj_t * obj, struct _lv_obj_t * parent);
/**
* Swap the positions of two objects.
* When used in listboxes, it can be used to sort the listbox items.
* @param obj1 pointer to the first object
* @param obj2 pointer to the second object
*/
void lv_obj_swap(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2);
/**
* moves the object to the given index in its parent.
* When used in listboxes, it can be used to sort the listbox items.
* @param obj pointer to the object to be moved.
* @param index new index in parent. -1 to count from the back
* @note to move to the background: lv_obj_move_to_index(obj, 0)
* @note to move forward (up): lv_obj_move_to_index(obj, lv_obj_get_index(obj) - 1)
*/
void lv_obj_move_to_index(struct _lv_obj_t * obj, int32_t index);
/**
* Get the screen of an object
* @param obj pointer to an object
* @return pointer to the object's screen
*/
struct _lv_obj_t * lv_obj_get_screen(const struct _lv_obj_t * obj);
/**
* Get the display of the object
* @param obj pointer to an object
* @return pointer to the object's display
*/
lv_disp_t * lv_obj_get_disp(const struct _lv_obj_t * obj);
/**
* Get the parent of an object
* @param obj pointer to an object
* @return the parent of the object. (NULL if `obj` was a screen)
*/
struct _lv_obj_t * lv_obj_get_parent(const struct _lv_obj_t * obj);
/**
* Get the child of an object by the child's index.
* @param obj pointer to an object whose child should be get
* @param id the index of the child.
* 0: the oldest (firstly created) child
* 1: the second oldest
* child count-1: the youngest
* -1: the youngest
* -2: the second youngest
* @return pointer to the child or NULL if the index was invalid
*/
struct _lv_obj_t * lv_obj_get_child(const struct _lv_obj_t * obj, int32_t id);
/**
* Get the number of children
* @param obj pointer to an object
* @return the number of children
*/
uint32_t lv_obj_get_child_cnt(const struct _lv_obj_t * obj);
/**
* Get the index of a child.
* @param obj pointer to an object
* @return the child index of the object.
* E.g. 0: the oldest (firstly created child)
*/
uint32_t lv_obj_get_index(const struct _lv_obj_t * obj);
/**
* Iterate through all children of any object.
* @param start_obj start integrating from this object
* @param cb call this callback on the objects
* @param user_data pointer to any user related data (will be passed to `cb`)
*/
void lv_obj_tree_walk(struct _lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OBJ_TREE_H*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,115 @@
/**
* @file lv_refr.h
*
*/
#ifndef LV_REFR_H
#define LV_REFR_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_obj.h"
#include <stdbool.h>
/*********************
* DEFINES
*********************/
#define LV_REFR_TASK_PRIO LV_TASK_PRIO_MID
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Initialize the screen refresh subsystem
*/
void _lv_refr_init(void);
/**
* Redraw the invalidated areas now.
* Normally the redrawing is periodically executed in `lv_timer_handler` but a long blocking process
* can prevent the call of `lv_timer_handler`. In this case if the GUI is updated in the process
* (e.g. progress bar) this function can be called when the screen should be updated.
* @param disp pointer to display to refresh. NULL to refresh all displays.
*/
void lv_refr_now(lv_disp_t * disp);
/**
* Redrawn on object an all its children using the passed draw context
* @param draw pointer to an initialized draw context
* @param obj the start object from the redraw should start
*/
void lv_obj_redraw(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj);
/**
* Invalidate an area on display to redraw it
* @param area_p pointer to area which should be invalidated (NULL: delete the invalidated areas)
* @param disp pointer to display where the area should be invalidated (NULL can be used if there is
* only one display)
*/
void _lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p);
/**
* Get the display which is being refreshed
* @return the display being refreshed
*/
lv_disp_t * _lv_refr_get_disp_refreshing(void);
/**
* Set the display which is being refreshed.
* It shouldn't be used directly by the user.
* It can be used to trick the drawing functions about there is an active display.
* @param the display being refreshed
*/
void _lv_refr_set_disp_refreshing(lv_disp_t * disp);
#if LV_USE_PERF_MONITOR
/**
* Reset FPS counter
*/
void lv_refr_reset_fps_counter(void);
/**
* Get the average FPS
* @return the average FPS
*/
uint32_t lv_refr_get_fps_avg(void);
#endif
/**
* Called periodically to handle the refreshing
* @param timer pointer to the timer itself
*/
void _lv_disp_refr_timer(lv_timer_t * timer);
/**********************
* STATIC FUNCTIONS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_REFR_H*/

Binary file not shown.

View File

@ -0,0 +1,120 @@
/**
*@file lv_theme.h
*
*/
#ifndef LV_THEME_H
#define LV_THEME_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../core/lv_obj.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct _lv_theme_t;
struct _lv_disp_t;
typedef void (*lv_theme_apply_cb_t)(struct _lv_theme_t *, lv_obj_t *);
typedef struct _lv_theme_t {
lv_theme_apply_cb_t apply_cb;
struct _lv_theme_t * parent; /**< Apply the current theme's style on top of this theme.*/
void * user_data;
struct _lv_disp_t * disp;
lv_color_t color_primary;
lv_color_t color_secondary;
const lv_font_t * font_small;
const lv_font_t * font_normal;
const lv_font_t * font_large;
uint32_t flags; /*Any custom flag used by the theme*/
} lv_theme_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Get the theme assigned to the display of the object
* @param obj pointer to a theme object
* @return the theme of the object's display (can be NULL)
*/
lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj);
/**
* Apply the active theme on an object
* @param obj pointer to an object
*/
void lv_theme_apply(lv_obj_t * obj);
/**
* Set a base theme for a theme.
* The styles from the base them will be added before the styles of the current theme.
* Arbitrary long chain of themes can be created by setting base themes.
* @param new_theme pointer to theme which base should be set
* @param parent pointer to the base theme
*/
void lv_theme_set_parent(lv_theme_t * new_theme, lv_theme_t * parent);
/**
* Set an apply callback for a theme.
* The apply callback is used to add styles to different objects
* @param theme pointer to theme which callback should be set
* @param apply_cb pointer to the callback
*/
void lv_theme_set_apply_cb(lv_theme_t * theme, lv_theme_apply_cb_t apply_cb);
/**
* Get the small font of the theme
* @param obj pointer to an object
* @return pointer to the font
*/
const lv_font_t * lv_theme_get_font_small(lv_obj_t * obj);
/**
* Get the normal font of the theme
* @param obj pointer to an object
* @return pointer to the font
*/
const lv_font_t * lv_theme_get_font_normal(lv_obj_t * obj);
/**
* Get the subtitle font of the theme
* @param obj pointer to an object
* @return pointer to the font
*/
const lv_font_t * lv_theme_get_font_large(lv_obj_t * obj);
/**
* Get the primary color of the theme
* @param obj pointer to an object
* @return the color
*/
lv_color_t lv_theme_get_color_primary(lv_obj_t * obj);
/**
* Get the secondary color of the theme
* @param obj pointer to an object
* @return the color
*/
lv_color_t lv_theme_get_color_secondary(lv_obj_t * obj);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_THEME_H*/

View File

@ -0,0 +1,6 @@
CSRCS += lv_gpu_arm2d.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d"

View File

@ -0,0 +1,51 @@
/**
* @file lv_gpu_arm2d.h
*
*/
#ifndef LV_GPU_ARM2D_H
#define LV_GPU_ARM2D_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../misc/lv_color.h"
#include "../../hal/lv_hal_disp.h"
#include "../sw/lv_draw_sw.h"
#if LV_USE_GPU_ARM2D
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef lv_draw_sw_ctx_t lv_draw_arm2d_ctx_t;
struct _lv_disp_drv_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_arm2d_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_arm2d_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_ARM2D*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_GPU_ARM2D_H*/

View File

@ -0,0 +1,219 @@
/**
* @file lv_draw.h
*
*/
#ifndef LV_DRAW_H
#define LV_DRAW_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#include "../misc/lv_style.h"
#include "../misc/lv_txt.h"
#include "lv_img_decoder.h"
#include "lv_img_cache.h"
#include "lv_draw_rect.h"
#include "lv_draw_label.h"
#include "lv_draw_img.h"
#include "lv_draw_line.h"
#include "lv_draw_triangle.h"
#include "lv_draw_arc.h"
#include "lv_draw_mask.h"
#include "lv_draw_transform.h"
#include "lv_draw_layer.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
void * user_data;
} lv_draw_mask_t;
typedef struct _lv_draw_layer_ctx_t {
lv_area_t area_full;
lv_area_t area_act;
lv_coord_t max_row_with_alpha;
lv_coord_t max_row_with_no_alpha;
void * buf;
struct {
const lv_area_t * clip_area;
lv_area_t * buf_area;
void * buf;
bool screen_transp;
} original;
} lv_draw_layer_ctx_t;
typedef struct _lv_draw_ctx_t {
/**
* Pointer to a buffer to draw into
*/
void * buf;
/**
* The position and size of `buf` (absolute coordinates)
*/
lv_area_t * buf_area;
/**
* The current clip area with absolute coordinates, always the same or smaller than `buf_area`
*/
const lv_area_t * clip_area;
void (*init_buf)(struct _lv_draw_ctx_t * draw_ctx);
void (*draw_rect)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
void (*draw_arc)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
uint16_t radius, uint16_t start_angle, uint16_t end_angle);
void (*draw_img_decoded)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format);
lv_res_t (*draw_img)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
const lv_area_t * coords, const void * src);
void (*draw_letter)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
uint32_t letter);
void (*draw_line)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
const lv_point_t * point2);
void (*draw_polygon)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc,
const lv_point_t * points, uint16_t point_cnt);
/**
* Get an area of a transformed image (zoomed and/or rotated)
* @param draw_ctx pointer to a draw context
* @param dest_area get this area of the result image. It assumes that the original image is placed to the 0;0 position.
* @param src_buf the source image
* @param src_w width of the source image in [px]
* @param src_h height of the source image in [px]
* @param src_stride the stride in [px].
* @param draw_dsc an `lv_draw_img_dsc_t` descriptor containing the transformation parameters
* @param cf the color format of `src_buf`
* @param cbuf place the colors of the pixels on `dest_area` here in RGB format
* @param abuf place the opacity of the pixels on `dest_area` here
*/
void (*draw_transform)(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf,
lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride,
const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf);
/**
* Replace the buffer with a rect without decoration like radius or borders
*/
void (*draw_bg)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_area_t * coords);
/**
* Wait until all background operations are finished. (E.g. GPU operations)
*/
void (*wait_for_finish)(struct _lv_draw_ctx_t * draw_ctx);
/**
* Copy an area from buffer to an other
* @param draw_ctx pointer to a draw context
* @param dest_buf copy the buffer into this buffer
* @param dest_stride the width of the dest_buf in pixels
* @param dest_area the destination area
* @param src_buf copy from this buffer
* @param src_stride the width of src_buf in pixels
* @param src_area the source area.
*
* @note dest_area and src_area must have the same width and height
* but can have different x and y position.
* @note dest_area and src_area must be clipped to the real dimensions of the buffers
*/
void (*buffer_copy)(struct _lv_draw_ctx_t * draw_ctx, void * dest_buf, lv_coord_t dest_stride,
const lv_area_t * dest_area,
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area);
/**
* Initialize a new layer context.
* The original buffer and area data are already saved from `draw_ctx` to `layer_ctx`
* @param draw_ctx pointer to the current draw context
* @param layer_area the coordinates of the layer
* @param flags OR-ed flags from @lv_draw_layer_flags_t
* @return pointer to the layer context, or NULL on error
*/
struct _lv_draw_layer_ctx_t * (*layer_init)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
lv_draw_layer_flags_t flags);
/**
* Adjust the layer_ctx and/or draw_ctx based on the `layer_ctx->area_act`.
* It's called only if flags has `LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE`
* @param draw_ctx pointer to the current draw context
* @param layer_ctx pointer to a layer context
* @param flags OR-ed flags from @lv_draw_layer_flags_t
*/
void (*layer_adjust)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
lv_draw_layer_flags_t flags);
/**
* Blend a rendered layer to `layer_ctx->area_act`
* @param draw_ctx pointer to the current draw context
* @param layer_ctx pointer to a layer context
* @param draw_dsc pointer to an image draw descriptor
*/
void (*layer_blend)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
const lv_draw_img_dsc_t * draw_dsc);
/**
* Destroy a layer context. The original buffer and area data of the `draw_ctx` will be restored
* and the `layer_ctx` itself will be freed automatically.
* @param draw_ctx pointer to the current draw context
* @param layer_ctx pointer to a layer context
*/
void (*layer_destroy)(struct _lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx);
/**
* Size of a layer context in bytes.
*/
size_t layer_instance_size;
#if LV_USE_USER_DATA
void * user_data;
#endif
} lv_draw_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_init(void);
void lv_draw_wait_for_finish(lv_draw_ctx_t * draw_ctx);
/**********************
* GLOBAL VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* POST INCLUDES
*********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_H*/

View File

@ -0,0 +1,25 @@
CSRCS += lv_draw_arc.c
CSRCS += lv_draw.c
CSRCS += lv_draw_img.c
CSRCS += lv_draw_label.c
CSRCS += lv_draw_line.c
CSRCS += lv_draw_mask.c
CSRCS += lv_draw_rect.c
CSRCS += lv_draw_transform.c
CSRCS += lv_draw_layer.c
CSRCS += lv_draw_triangle.c
CSRCS += lv_img_buf.c
CSRCS += lv_img_cache.c
CSRCS += lv_img_decoder.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw"
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d/lv_draw_arm2d.mk
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/lv_draw_nxp.mk
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl/lv_draw_sdl.mk
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d/lv_draw_stm32_dma2d.mk
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw/lv_draw_sw.mk
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/swm341_dma2d/lv_draw_swm341_dma2d.mk

View File

@ -0,0 +1,83 @@
/**
* @file lv_draw_arc.h
*
*/
#ifndef LV_DRAW_ARC_H
#define LV_DRAW_ARC_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#include "../misc/lv_color.h"
#include "../misc/lv_area.h"
#include "../misc/lv_style.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_color_t color;
lv_coord_t width;
uint16_t start_angle;
uint16_t end_angle;
const void * img_src;
lv_opa_t opa;
lv_blend_mode_t blend_mode : 2;
uint8_t rounded : 1;
} lv_draw_arc_dsc_t;
struct _lv_draw_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc);
/**
* Draw an arc. (Can draw pie too with great thickness.)
* @param center_x the x coordinate of the center of the arc
* @param center_y the y coordinate of the center of the arc
* @param radius the radius of the arc
* @param mask the arc will be drawn only in this mask
* @param start_angle the start angle of the arc (0 deg on the bottom, 90 deg on the right)
* @param end_angle the end angle of the arc
* @param clip_area the arc will be drawn only in this area
* @param dsc pointer to an initialized `lv_draw_line_dsc_t` variable
*/
void lv_draw_arc(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
uint16_t radius, uint16_t start_angle, uint16_t end_angle);
/**
* Get an area the should be invalidated when the arcs angle changed between start_angle and end_ange
* @param x the x coordinate of the center of the arc
* @param y the y coordinate of the center of the arc
* @param radius the radius of the arc
* @param start_angle the start angle of the arc (0 deg on the bottom, 90 deg on the right)
* @param end_angle the end angle of the arc
* @param w width of the arc
* @param rounded true: the arc is rounded
* @param area store the area to invalidate here
*/
void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle,
lv_coord_t w, bool rounded, lv_area_t * area);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_ARC_H*/

View File

@ -0,0 +1,104 @@
/**
* @file lv_draw_img.h
*
*/
#ifndef LV_DRAW_IMG_H
#define LV_DRAW_IMG_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_img_decoder.h"
#include "lv_img_buf.h"
#include "../misc/lv_style.h"
/*********************
* DEFINES
*********************/
/**********************
* MACROS
**********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
int16_t angle;
uint16_t zoom;
lv_point_t pivot;
lv_color_t recolor;
lv_opa_t recolor_opa;
lv_opa_t opa;
lv_blend_mode_t blend_mode : 4;
int32_t frame_id;
uint8_t antialias : 1;
} lv_draw_img_dsc_t;
struct _lv_draw_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_img_dsc_init(lv_draw_img_dsc_t * dsc);
/**
* Draw an image
* @param coords the coordinates of the image
* @param mask the image will be drawn only in this area
* @param src pointer to a lv_color_t array which contains the pixels of the image
* @param dsc pointer to an initialized `lv_draw_img_dsc_t` variable
*/
void lv_draw_img(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const lv_area_t * coords,
const void * src);
void lv_draw_img_decoded(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format);
/**
* Get the type of an image source
* @param src pointer to an image source:
* - pointer to an 'lv_img_t' variable (image stored internally and compiled into the code)
* - a path to a file (e.g. "S:/folder/image.bin")
* - or a symbol (e.g. LV_SYMBOL_CLOSE)
* @return type of the image source LV_IMG_SRC_VARIABLE/FILE/SYMBOL/UNKNOWN
*/
lv_img_src_t lv_img_src_get_type(const void * src);
/**
* Get the pixel size of a color format in bits
* @param cf a color format (`LV_IMG_CF_...`)
* @return the pixel size in bits
*/
uint8_t lv_img_cf_get_px_size(lv_img_cf_t cf);
/**
* Check if a color format is chroma keyed or not
* @param cf a color format (`LV_IMG_CF_...`)
* @return true: chroma keyed; false: not chroma keyed
*/
bool lv_img_cf_is_chroma_keyed(lv_img_cf_t cf);
/**
* Check if a color format has alpha channel or not
* @param cf a color format (`LV_IMG_CF_...`)
* @return true: has alpha channel; false: doesn't have alpha channel
*/
bool lv_img_cf_has_alpha(lv_img_cf_t cf);
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_IMG_H*/

View File

@ -0,0 +1,100 @@
/**
* @file lv_draw_label.h
*
*/
#ifndef LV_DRAW_LABEL_H
#define LV_DRAW_LABEL_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../misc/lv_bidi.h"
#include "../misc/lv_txt.h"
#include "../misc/lv_color.h"
#include "../misc/lv_style.h"
/*********************
* DEFINES
*********************/
#define LV_DRAW_LABEL_NO_TXT_SEL (0xFFFF)
/**********************
* TYPEDEFS
**********************/
typedef struct {
const lv_font_t * font;
uint32_t sel_start;
uint32_t sel_end;
lv_color_t color;
lv_color_t sel_color;
lv_color_t sel_bg_color;
lv_coord_t line_space;
lv_coord_t letter_space;
lv_coord_t ofs_x;
lv_coord_t ofs_y;
lv_opa_t opa;
lv_base_dir_t bidi_dir;
lv_text_align_t align;
lv_text_flag_t flag;
lv_text_decor_t decor : 3;
lv_blend_mode_t blend_mode: 3;
} lv_draw_label_dsc_t;
/** Store some info to speed up drawing of very large texts
* It takes a lot of time to get the first visible character because
* all the previous characters needs to be checked to calculate the positions.
* This structure stores an earlier (e.g. at -1000 px) coordinate and the index of that line.
* Therefore the calculations can start from here.*/
typedef struct _lv_draw_label_hint_t {
/** Index of the line at `y` coordinate*/
int32_t line_start;
/** Give the `y` coordinate of the first letter at `line start` index. Relative to the label's coordinates*/
int32_t y;
/** The 'y1' coordinate of the label when the hint was saved.
* Used to invalidate the hint if the label has moved too much.*/
int32_t coord_y;
} lv_draw_label_hint_t;
struct _lv_draw_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
LV_ATTRIBUTE_FAST_MEM void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc);
/**
* Write a text
* @param coords coordinates of the label
* @param mask the label will be drawn only in this area
* @param dsc pointer to draw descriptor
* @param txt `\0` terminated text to write
* @param hint pointer to a `lv_draw_label_hint_t` variable.
* It is managed by the draw to speed up the drawing of very long texts (thousands of lines).
*/
LV_ATTRIBUTE_FAST_MEM void lv_draw_label(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc,
const lv_area_t * coords, const char * txt, lv_draw_label_hint_t * hint);
void lv_draw_letter(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
uint32_t letter);
/***********************
* GLOBAL VARIABLES
***********************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_LABEL_H*/

View File

@ -0,0 +1,83 @@
/**
* @file lv_draw_layer.h
*
*/
#ifndef LV_DRAW_LAYER_H
#define LV_DRAW_LAYER_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct _lv_draw_ctx_t;
struct _lv_draw_layer_ctx_t;
typedef enum {
LV_DRAW_LAYER_FLAG_NONE,
LV_DRAW_LAYER_FLAG_HAS_ALPHA,
LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE,
} lv_draw_layer_flags_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Create a new layer context. It is used to start and independent rendering session
* with the current draw_ctx
* @param draw_ctx pointer to the current draw context
* @param layer_area the coordinates of the layer
* @param flags OR-ed flags from @lv_draw_layer_flags_t
* @return pointer to the layer context, or NULL on error
*/
struct _lv_draw_layer_ctx_t * lv_draw_layer_create(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * layer_area,
lv_draw_layer_flags_t flags);
/**
* Adjust the layer_ctx and/or draw_ctx based on the `layer_ctx->area_act`.
* It's called only if flags has `LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE`
* @param draw_ctx pointer to the current draw context
* @param layer_ctx pointer to a layer context
* @param flags OR-ed flags from @lv_draw_layer_flags_t
*/
void lv_draw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
lv_draw_layer_flags_t flags);
/**
* Blend a rendered layer to `layer_ctx->area_act`
* @param draw_ctx pointer to the current draw context
* @param layer_ctx pointer to a layer context
* @param draw_dsc pointer to an image draw descriptor
*/
void lv_draw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
lv_draw_img_dsc_t * draw_dsc);
/**
* Destroy a layer context.
* @param draw_ctx pointer to the current draw context
* @param layer_ctx pointer to a layer context
*/
void lv_draw_layer_destroy(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_LAYER_H*/

View File

@ -0,0 +1,67 @@
/**
* @file lv_draw_line.h
*
*/
#ifndef LV_DRAW_LINE_H
#define LV_DRAW_LINE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#include "../misc/lv_color.h"
#include "../misc/lv_area.h"
#include "../misc/lv_style.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_color_t color;
lv_coord_t width;
lv_coord_t dash_width;
lv_coord_t dash_gap;
lv_opa_t opa;
lv_blend_mode_t blend_mode : 2;
uint8_t round_start : 1;
uint8_t round_end : 1;
uint8_t raw_end : 1; /*Do not bother with perpendicular line ending if it's not visible for any reason*/
} lv_draw_line_dsc_t;
struct _lv_draw_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
LV_ATTRIBUTE_FAST_MEM void lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc);
/**
* Draw a line
* @param point1 first point of the line
* @param point2 second point of the line
* @param clip the line will be drawn only in this area
* @param dsc pointer to an initialized `lv_draw_line_dsc_t` variable
*/
void lv_draw_line(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
const lv_point_t * point2);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_LINE_H*/

View File

@ -0,0 +1,394 @@
/**
* @file lv_draw_mask.h
*
*/
#ifndef LV_DRAW_MASK_H
#define LV_DRAW_MASK_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <stdbool.h>
#include "../misc/lv_area.h"
#include "../misc/lv_color.h"
#include "../misc/lv_math.h"
/*********************
* DEFINES
*********************/
#define LV_MASK_ID_INV (-1)
#if LV_DRAW_COMPLEX
# define _LV_MASK_MAX_NUM 16
#else
# define _LV_MASK_MAX_NUM 1
#endif
/**********************
* TYPEDEFS
**********************/
enum {
LV_DRAW_MASK_RES_TRANSP,
LV_DRAW_MASK_RES_FULL_COVER,
LV_DRAW_MASK_RES_CHANGED,
LV_DRAW_MASK_RES_UNKNOWN
};
typedef uint8_t lv_draw_mask_res_t;
typedef struct {
void * param;
void * custom_id;
} _lv_draw_mask_saved_t;
typedef _lv_draw_mask_saved_t _lv_draw_mask_saved_arr_t[_LV_MASK_MAX_NUM];
#if LV_DRAW_COMPLEX == 0
static inline uint8_t lv_draw_mask_get_cnt(void)
{
return 0;
}
static inline bool lv_draw_mask_is_any(const lv_area_t * a)
{
LV_UNUSED(a);
return false;
}
#endif
#if LV_DRAW_COMPLEX
enum {
LV_DRAW_MASK_TYPE_LINE,
LV_DRAW_MASK_TYPE_ANGLE,
LV_DRAW_MASK_TYPE_RADIUS,
LV_DRAW_MASK_TYPE_FADE,
LV_DRAW_MASK_TYPE_MAP,
LV_DRAW_MASK_TYPE_POLYGON,
};
typedef uint8_t lv_draw_mask_type_t;
enum {
LV_DRAW_MASK_LINE_SIDE_LEFT = 0,
LV_DRAW_MASK_LINE_SIDE_RIGHT,
LV_DRAW_MASK_LINE_SIDE_TOP,
LV_DRAW_MASK_LINE_SIDE_BOTTOM,
};
/**
* A common callback type for every mask type.
* Used internally by the library.
*/
typedef lv_draw_mask_res_t (*lv_draw_mask_xcb_t)(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y,
lv_coord_t len,
void * p);
typedef uint8_t lv_draw_mask_line_side_t;
typedef struct {
lv_draw_mask_xcb_t cb;
lv_draw_mask_type_t type;
} _lv_draw_mask_common_dsc_t;
typedef struct {
/*The first element must be the common descriptor*/
_lv_draw_mask_common_dsc_t dsc;
struct {
/*First point*/
lv_point_t p1;
/*Second point*/
lv_point_t p2;
/*Which side to keep?*/
lv_draw_mask_line_side_t side : 2;
} cfg;
/*A point of the line*/
lv_point_t origo;
/*X / (1024*Y) steepness (X is 0..1023 range). What is the change of X in 1024 Y?*/
int32_t xy_steep;
/*Y / (1024*X) steepness (Y is 0..1023 range). What is the change of Y in 1024 X?*/
int32_t yx_steep;
/*Helper which stores yx_steep for flat lines and xy_steep for steep (non flat) lines*/
int32_t steep;
/*Steepness in 1 px in 0..255 range. Used only by flat lines.*/
int32_t spx;
/*1: It's a flat line? (Near to horizontal)*/
uint8_t flat : 1;
/*Invert the mask. The default is: Keep the left part.
*It is used to select left/right/top/bottom*/
uint8_t inv: 1;
} lv_draw_mask_line_param_t;
typedef struct {
/*The first element must be the common descriptor*/
_lv_draw_mask_common_dsc_t dsc;
struct {
lv_point_t vertex_p;
lv_coord_t start_angle;
lv_coord_t end_angle;
} cfg;
lv_draw_mask_line_param_t start_line;
lv_draw_mask_line_param_t end_line;
uint16_t delta_deg;
} lv_draw_mask_angle_param_t;
typedef struct {
uint8_t * buf;
lv_opa_t * cir_opa; /*Opacity of values on the circumference of an 1/4 circle*/
uint16_t * x_start_on_y; /*The x coordinate of the circle for each y value*/
uint16_t * opa_start_on_y; /*The index of `cir_opa` for each y value*/
int32_t life; /*How many times the entry way used*/
uint32_t used_cnt; /*Like a semaphore to count the referencing masks*/
lv_coord_t radius; /*The radius of the entry*/
} _lv_draw_mask_radius_circle_dsc_t;
typedef _lv_draw_mask_radius_circle_dsc_t _lv_draw_mask_radius_circle_dsc_arr_t[LV_CIRCLE_CACHE_SIZE];
typedef struct {
/*The first element must be the common descriptor*/
_lv_draw_mask_common_dsc_t dsc;
struct {
lv_area_t rect;
lv_coord_t radius;
/*Invert the mask. 0: Keep the pixels inside.*/
uint8_t outer: 1;
} cfg;
_lv_draw_mask_radius_circle_dsc_t * circle;
} lv_draw_mask_radius_param_t;
typedef struct {
/*The first element must be the common descriptor*/
_lv_draw_mask_common_dsc_t dsc;
struct {
lv_area_t coords;
lv_coord_t y_top;
lv_coord_t y_bottom;
lv_opa_t opa_top;
lv_opa_t opa_bottom;
} cfg;
} lv_draw_mask_fade_param_t;
typedef struct _lv_draw_mask_map_param_t {
/*The first element must be the common descriptor*/
_lv_draw_mask_common_dsc_t dsc;
struct {
lv_area_t coords;
const lv_opa_t * map;
} cfg;
} lv_draw_mask_map_param_t;
typedef struct {
/*The first element must be the common descriptor*/
_lv_draw_mask_common_dsc_t dsc;
struct {
lv_point_t * points;
uint16_t point_cnt;
} cfg;
} lv_draw_mask_polygon_param_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Add a draw mask. Everything drawn after it (until removing the mask) will be affected by the mask.
* @param param an initialized mask parameter. Only the pointer is saved.
* @param custom_id a custom pointer to identify the mask. Used in `lv_draw_mask_remove_custom`.
* @return the an integer, the ID of the mask. Can be used in `lv_draw_mask_remove_id`.
*/
int16_t lv_draw_mask_add(void * param, void * custom_id);
//! @cond Doxygen_Suppress
/**
* Apply the added buffers on a line. Used internally by the library's drawing routines.
* @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`.
* @param abs_x absolute X coordinate where the line to calculate start
* @param abs_y absolute Y coordinate where the line to calculate start
* @param len length of the line to calculate (in pixel count)
* @return One of these values:
* - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero
* - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged
* - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line
*/
LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y,
lv_coord_t len);
/**
* Apply the specified buffers on a line. Used internally by the library's drawing routines.
* @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`.
* @param abs_x absolute X coordinate where the line to calculate start
* @param abs_y absolute Y coordinate where the line to calculate start
* @param len length of the line to calculate (in pixel count)
* @param ids ID array of added buffers
* @param ids_count number of ID array
* @return One of these values:
* - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero
* - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged
* - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line
*/
LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply_ids(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y,
lv_coord_t len, const int16_t * ids, int16_t ids_count);
//! @endcond
/**
* Remove a mask with a given ID
* @param id the ID of the mask. Returned by `lv_draw_mask_add`
* @return the parameter of the removed mask.
* If more masks have `custom_id` ID then the last mask's parameter will be returned
*/
void * lv_draw_mask_remove_id(int16_t id);
/**
* Remove all mask with a given custom ID
* @param custom_id a pointer used in `lv_draw_mask_add`
* @return return the parameter of the removed mask.
* If more masks have `custom_id` ID then the last mask's parameter will be returned
*/
void * lv_draw_mask_remove_custom(void * custom_id);
/**
* Free the data from the parameter.
* It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom`
* Needs to be called only in special cases when the mask is not added by `lv_draw_mask_add`
* and not removed by `lv_draw_mask_remove_id` or `lv_draw_mask_remove_custom`
* @param p pointer to a mask parameter
*/
void lv_draw_mask_free_param(void * p);
/**
* Called by LVGL the rendering of a screen is ready to clean up
* the temporal (cache) data of the masks
*/
void _lv_draw_mask_cleanup(void);
//! @cond Doxygen_Suppress
/**
* Count the currently added masks
* @return number of active masks
*/
LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void);
/**
* Check if there is any added draw mask
* @param a an area to test for affecting masks.
* @return true: there is t least 1 draw mask; false: there are no draw masks
*/
bool lv_draw_mask_is_any(const lv_area_t * a);
//! @endcond
/**
*Initialize a line mask from two points.
* @param param pointer to a `lv_draw_mask_param_t` to initialize
* @param p1x X coordinate of the first point of the line
* @param p1y Y coordinate of the first point of the line
* @param p2x X coordinate of the second point of the line
* @param p2y y coordinate of the second point of the line
* @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep.
* With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept
* With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept
*/
void lv_draw_mask_line_points_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x,
lv_coord_t p2y, lv_draw_mask_line_side_t side);
/**
*Initialize a line mask from a point and an angle.
* @param param pointer to a `lv_draw_mask_param_t` to initialize
* @param px X coordinate of a point of the line
* @param py X coordinate of a point of the line
* @param angle right 0 deg, bottom: 90
* @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep.
* With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept
* With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept
*/
void lv_draw_mask_line_angle_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t py, int16_t angle,
lv_draw_mask_line_side_t side);
/**
* Initialize an angle mask.
* @param param pointer to a `lv_draw_mask_param_t` to initialize
* @param vertex_x X coordinate of the angle vertex (absolute coordinates)
* @param vertex_y Y coordinate of the angle vertex (absolute coordinates)
* @param start_angle start angle in degrees. 0 deg on the right, 90 deg, on the bottom
* @param end_angle end angle
*/
void lv_draw_mask_angle_init(lv_draw_mask_angle_param_t * param, lv_coord_t vertex_x, lv_coord_t vertex_y,
lv_coord_t start_angle, lv_coord_t end_angle);
/**
* Initialize a fade mask.
* @param param pointer to an `lv_draw_mask_radius_param_t` to initialize
* @param rect coordinates of the rectangle to affect (absolute coordinates)
* @param radius radius of the rectangle
* @param inv true: keep the pixels inside the rectangle; keep the pixels outside of the rectangle
*/
void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area_t * rect, lv_coord_t radius, bool inv);
/**
* Initialize a fade mask.
* @param param pointer to a `lv_draw_mask_param_t` to initialize
* @param coords coordinates of the area to affect (absolute coordinates)
* @param opa_top opacity on the top
* @param y_top at which coordinate start to change to opacity to `opa_bottom`
* @param opa_bottom opacity at the bottom
* @param y_bottom at which coordinate reach `opa_bottom`.
*/
void lv_draw_mask_fade_init(lv_draw_mask_fade_param_t * param, const lv_area_t * coords, lv_opa_t opa_top,
lv_coord_t y_top,
lv_opa_t opa_bottom, lv_coord_t y_bottom);
/**
* Initialize a map mask.
* @param param pointer to a `lv_draw_mask_param_t` to initialize
* @param coords coordinates of the map (absolute coordinates)
* @param map array of bytes with the mask values
*/
void lv_draw_mask_map_init(lv_draw_mask_map_param_t * param, const lv_area_t * coords, const lv_opa_t * map);
void lv_draw_mask_polygon_init(lv_draw_mask_polygon_param_t * param, const lv_point_t * points, uint16_t point_cnt);
#endif /*LV_DRAW_COMPLEX*/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_MASK_H*/

View File

@ -0,0 +1,96 @@
/**
* @file lv_draw_rect.h
*
*/
#ifndef LV_DRAW_RECT_H
#define LV_DRAW_RECT_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#include "../misc/lv_color.h"
#include "../misc/lv_area.h"
#include "../misc/lv_style.h"
#include "sw/lv_draw_sw_gradient.h"
/*********************
* DEFINES
*********************/
#define LV_RADIUS_CIRCLE 0x7FFF /**< A very big radius to always draw as circle*/
LV_EXPORT_CONST_INT(LV_RADIUS_CIRCLE);
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_coord_t radius;
lv_blend_mode_t blend_mode;
/*Background*/
lv_opa_t bg_opa;
lv_color_t bg_color; /**< First element of a gradient is a color, so it maps well here*/
lv_grad_dsc_t bg_grad;
/*Background img*/
const void * bg_img_src;
const void * bg_img_symbol_font;
lv_color_t bg_img_recolor;
lv_opa_t bg_img_opa;
lv_opa_t bg_img_recolor_opa;
uint8_t bg_img_tiled;
/*Border*/
lv_color_t border_color;
lv_coord_t border_width;
lv_opa_t border_opa;
uint8_t border_post : 1; /*There is a border it will be drawn later.*/
lv_border_side_t border_side : 5;
/*Outline*/
lv_color_t outline_color;
lv_coord_t outline_width;
lv_coord_t outline_pad;
lv_opa_t outline_opa;
/*Shadow*/
lv_color_t shadow_color;
lv_coord_t shadow_width;
lv_coord_t shadow_ofs_x;
lv_coord_t shadow_ofs_y;
lv_coord_t shadow_spread;
lv_opa_t shadow_opa;
} lv_draw_rect_dsc_t;
struct _lv_draw_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
LV_ATTRIBUTE_FAST_MEM void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc);
/**
* Draw a rectangle
* @param coords the coordinates of the rectangle
* @param clip the rectangle will be drawn only in this area
* @param dsc pointer to an initialized `lv_draw_rect_dsc_t` variable
*/
void lv_draw_rect(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_RECT_H*/

View File

@ -0,0 +1,44 @@
/**
* @file lv_draw_transform.h
*
*/
#ifndef LV_DRAW_TRANSFORM_H
#define LV_DRAW_TRANSFORM_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#include "../misc/lv_area.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct _lv_draw_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_transform(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf,
lv_coord_t src_w, lv_coord_t src_h,
lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_TRANSFORM_H*/

View File

@ -0,0 +1,42 @@
/**
* @file lv_draw_triangle.h
*
*/
#ifndef LV_DRAW_TRIANGLE_H
#define LV_DRAW_TRIANGLE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw_rect.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[],
uint16_t point_cnt);
void lv_draw_triangle(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[]);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_TRIANGLE_H*/

View File

@ -0,0 +1,249 @@
/**
* @file lv_img_buf.h
*
*/
#ifndef LV_IMG_BUF_H
#define LV_IMG_BUF_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <stdbool.h>
#include "../misc/lv_color.h"
#include "../misc/lv_area.h"
/*********************
* DEFINES
*********************/
/*If image pixels contains alpha we need to know how much byte is a pixel*/
#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8
#define LV_IMG_PX_SIZE_ALPHA_BYTE 2
#elif LV_COLOR_DEPTH == 16
#define LV_IMG_PX_SIZE_ALPHA_BYTE 3
#elif LV_COLOR_DEPTH == 32
#define LV_IMG_PX_SIZE_ALPHA_BYTE 4
#endif
#define LV_IMG_BUF_SIZE_TRUE_COLOR(w, h) ((LV_COLOR_SIZE / 8) * w * h)
#define LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) ((LV_COLOR_SIZE / 8) * w * h)
#define LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) (LV_IMG_PX_SIZE_ALPHA_BYTE * w * h)
/*+ 1: to be sure no fractional row*/
#define LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) ((((w / 8) + 1) * h))
#define LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) ((((w / 4) + 1) * h))
#define LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) ((((w / 2) + 1) * h))
#define LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) ((w * h))
/*4 * X: for palette*/
#define LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) + 4 * 2)
#define LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) + 4 * 4)
#define LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) + 4 * 16)
#define LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) + 4 * 256)
#define _LV_ZOOM_INV_UPSCALE 5
/**********************
* TYPEDEFS
**********************/
/*Image color format*/
enum {
LV_IMG_CF_UNKNOWN = 0,
LV_IMG_CF_RAW, /**< Contains the file as it is. Needs custom decoder function*/
LV_IMG_CF_RAW_ALPHA, /**< Contains the file as it is. The image has alpha. Needs custom decoder
function*/
LV_IMG_CF_RAW_CHROMA_KEYED, /**< Contains the file as it is. The image is chroma keyed. Needs
custom decoder function*/
LV_IMG_CF_TRUE_COLOR, /**< Color format and depth should match with LV_COLOR settings*/
LV_IMG_CF_TRUE_COLOR_ALPHA, /**< Same as `LV_IMG_CF_TRUE_COLOR` but every pixel has an alpha byte*/
LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED, /**< Same as `LV_IMG_CF_TRUE_COLOR` but LV_COLOR_TRANSP pixels
will be transparent*/
LV_IMG_CF_INDEXED_1BIT, /**< Can have 2 different colors in a palette (can't be chroma keyed)*/
LV_IMG_CF_INDEXED_2BIT, /**< Can have 4 different colors in a palette (can't be chroma keyed)*/
LV_IMG_CF_INDEXED_4BIT, /**< Can have 16 different colors in a palette (can't be chroma keyed)*/
LV_IMG_CF_INDEXED_8BIT, /**< Can have 256 different colors in a palette (can't be chroma keyed)*/
LV_IMG_CF_ALPHA_1BIT, /**< Can have one color and it can be drawn or not*/
LV_IMG_CF_ALPHA_2BIT, /**< Can have one color but 4 different alpha value*/
LV_IMG_CF_ALPHA_4BIT, /**< Can have one color but 16 different alpha value*/
LV_IMG_CF_ALPHA_8BIT, /**< Can have one color but 256 different alpha value*/
LV_IMG_CF_RGB888,
LV_IMG_CF_RGBA8888,
LV_IMG_CF_RGBX8888,
LV_IMG_CF_RGB565,
LV_IMG_CF_RGBA5658,
LV_IMG_CF_RGB565A8,
LV_IMG_CF_RESERVED_15, /**< Reserved for further use.*/
LV_IMG_CF_RESERVED_16, /**< Reserved for further use.*/
LV_IMG_CF_RESERVED_17, /**< Reserved for further use.*/
LV_IMG_CF_RESERVED_18, /**< Reserved for further use.*/
LV_IMG_CF_RESERVED_19, /**< Reserved for further use.*/
LV_IMG_CF_RESERVED_20, /**< Reserved for further use.*/
LV_IMG_CF_RESERVED_21, /**< Reserved for further use.*/
LV_IMG_CF_RESERVED_22, /**< Reserved for further use.*/
LV_IMG_CF_RESERVED_23, /**< Reserved for further use.*/
LV_IMG_CF_USER_ENCODED_0, /**< User holder encoding format.*/
LV_IMG_CF_USER_ENCODED_1, /**< User holder encoding format.*/
LV_IMG_CF_USER_ENCODED_2, /**< User holder encoding format.*/
LV_IMG_CF_USER_ENCODED_3, /**< User holder encoding format.*/
LV_IMG_CF_USER_ENCODED_4, /**< User holder encoding format.*/
LV_IMG_CF_USER_ENCODED_5, /**< User holder encoding format.*/
LV_IMG_CF_USER_ENCODED_6, /**< User holder encoding format.*/
LV_IMG_CF_USER_ENCODED_7, /**< User holder encoding format.*/
};
typedef uint8_t lv_img_cf_t;
/**
* The first 8 bit is very important to distinguish the different source types.
* For more info see `lv_img_get_src_type()` in lv_img.c
* On big endian systems the order is reversed so cf and always_zero must be at
* the end of the struct.
*/
#if LV_BIG_ENDIAN_SYSTEM
typedef struct {
uint32_t h : 11; /*Height of the image map*/
uint32_t w : 11; /*Width of the image map*/
uint32_t reserved : 2; /*Reserved to be used later*/
uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a
non-printable character*/
uint32_t cf : 5; /*Color format: See `lv_img_color_format_t`*/
} lv_img_header_t;
#else
typedef struct {
uint32_t cf : 5; /*Color format: See `lv_img_color_format_t`*/
uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a
non-printable character*/
uint32_t reserved : 2; /*Reserved to be used later*/
uint32_t w : 11; /*Width of the image map*/
uint32_t h : 11; /*Height of the image map*/
} lv_img_header_t;
#endif
/** Image header it is compatible with
* the result from image converter utility*/
typedef struct {
lv_img_header_t header; /**< A header describing the basics of the image*/
uint32_t data_size; /**< Size of the image in bytes*/
const uint8_t * data; /**< Pointer to the data of the image*/
} lv_img_dsc_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Allocate an image buffer in RAM
* @param w width of image
* @param h height of image
* @param cf a color format (`LV_IMG_CF_...`)
* @return an allocated image, or NULL on failure
*/
lv_img_dsc_t * lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
/**
* Get the color of an image's pixel
* @param dsc an image descriptor
* @param x x coordinate of the point to get
* @param y x coordinate of the point to get
* @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used.
* Not used in other cases.
* @param safe true: check out of bounds
* @return color of the point
*/
lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color);
/**
* Get the alpha value of an image's pixel
* @param dsc pointer to an image descriptor
* @param x x coordinate of the point to set
* @param y x coordinate of the point to set
* @param safe true: check out of bounds
* @return alpha value of the point
*/
lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y);
/**
* Set the color of a pixel of an image. The alpha channel won't be affected.
* @param dsc pointer to an image descriptor
* @param x x coordinate of the point to set
* @param y x coordinate of the point to set
* @param c color of the point
* @param safe true: check out of bounds
*/
void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c);
/**
* Set the alpha value of a pixel of an image. The color won't be affected
* @param dsc pointer to an image descriptor
* @param x x coordinate of the point to set
* @param y x coordinate of the point to set
* @param opa the desired opacity
* @param safe true: check out of bounds
*/
void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa);
/**
* Set the palette color of an indexed image. Valid only for `LV_IMG_CF_INDEXED1/2/4/8`
* @param dsc pointer to an image descriptor
* @param id the palette color to set:
* - for `LV_IMG_CF_INDEXED1`: 0..1
* - for `LV_IMG_CF_INDEXED2`: 0..3
* - for `LV_IMG_CF_INDEXED4`: 0..15
* - for `LV_IMG_CF_INDEXED8`: 0..255
* @param c the color to set
*/
void lv_img_buf_set_palette(lv_img_dsc_t * dsc, uint8_t id, lv_color_t c);
/**
* Free an allocated image buffer
* @param dsc image buffer to free
*/
void lv_img_buf_free(lv_img_dsc_t * dsc);
/**
* Get the memory consumption of a raw bitmap, given color format and dimensions.
* @param w width
* @param h height
* @param cf color format
* @return size in bytes
*/
uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
/**
* Get the area of a rectangle if its rotated and scaled
* @param res store the coordinates here
* @param w width of the rectangle to transform
* @param h height of the rectangle to transform
* @param angle angle of rotation
* @param zoom zoom, (256 no zoom)
* @param pivot x,y pivot coordinates of rotation
*/
void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t h, int16_t angle, uint16_t zoom,
const lv_point_t * pivot);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_IMG_BUF_H*/

View File

@ -0,0 +1,78 @@
/**
* @file lv_img_cache.h
*
*/
#ifndef LV_IMG_CACHE_H
#define LV_IMG_CACHE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_img_decoder.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**
* When loading images from the network it can take a long time to download and decode the image.
*
* To avoid repeating this heavy load images can be cached.
*/
typedef struct {
lv_img_decoder_dsc_t dec_dsc; /**< Image information*/
/** Count the cache entries's life. Add `time_to_open` to `life` when the entry is used.
* Decrement all lifes by one every in every ::lv_img_cache_open.
* If life == 0 the entry can be reused*/
int32_t life;
} _lv_img_cache_entry_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Open an image using the image decoder interface and cache it.
* The image will be left open meaning if the image decoder open callback allocated memory then it will remain.
* The image is closed if a new image is opened and the new image takes its place in the cache.
* @param src source of the image. Path to file or pointer to an `lv_img_dsc_t` variable
* @param color The color of the image with `LV_IMG_CF_ALPHA_...`
* @param frame_id the index of the frame. Used only with animated images, set 0 for normal images
* @return pointer to the cache entry or NULL if can open the image
*/
_lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color, int32_t frame_id);
/**
* Set the number of images to be cached.
* More cached images mean more opened image at same time which might mean more memory usage.
* E.g. if 20 PNG or JPG images are open in the RAM they consume memory while opened in the cache.
* @param new_entry_cnt number of image to cache
*/
void lv_img_cache_set_size(uint16_t new_slot_num);
/**
* Invalidate an image source in the cache.
* Useful if the image source is updated therefore it needs to be cached again.
* @param src an image source path to a file or pointer to an `lv_img_dsc_t` variable.
*/
void lv_img_cache_invalidate_src(const void * src);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_IMG_CACHE_H*/

View File

@ -0,0 +1,278 @@
/**
* @file lv_img_decoder.h
*
*/
#ifndef LV_IMG_DECODER_H
#define LV_IMG_DECODER_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#include <stdint.h>
#include "lv_img_buf.h"
#include "../misc/lv_fs.h"
#include "../misc/lv_types.h"
#include "../misc/lv_area.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**
* Source of image.*/
enum {
LV_IMG_SRC_VARIABLE, /** Binary/C variable*/
LV_IMG_SRC_FILE, /** File in filesystem*/
LV_IMG_SRC_SYMBOL, /** Symbol (@ref lv_symbol_def.h)*/
LV_IMG_SRC_UNKNOWN, /** Unknown source*/
};
typedef uint8_t lv_img_src_t;
/*Decoder function definitions*/
struct _lv_img_decoder_dsc_t;
struct _lv_img_decoder_t;
/**
* Get info from an image and store in the `header`
* @param src the image source. Can be a pointer to a C array or a file name (Use
* `lv_img_src_get_type` to determine the type)
* @param header store the info here
* @return LV_RES_OK: info written correctly; LV_RES_INV: failed
*/
typedef lv_res_t (*lv_img_decoder_info_f_t)(struct _lv_img_decoder_t * decoder, const void * src,
lv_img_header_t * header);
/**
* Open an image for decoding. Prepare it as it is required to read it later
* @param decoder pointer to the decoder the function associated with
* @param dsc pointer to decoder descriptor. `src`, `color` are already initialized in it.
*/
typedef lv_res_t (*lv_img_decoder_open_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc);
/**
* Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`.
* Required only if the "open" function can't return with the whole decoded pixel array.
* @param decoder pointer to the decoder the function associated with
* @param dsc pointer to decoder descriptor
* @param x start x coordinate
* @param y start y coordinate
* @param len number of pixels to decode
* @param buf a buffer to store the decoded pixels
* @return LV_RES_OK: ok; LV_RES_INV: failed
*/
typedef lv_res_t (*lv_img_decoder_read_line_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc,
lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf);
/**
* Close the pending decoding. Free resources etc.
* @param decoder pointer to the decoder the function associated with
* @param dsc pointer to decoder descriptor
*/
typedef void (*lv_img_decoder_close_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc);
typedef struct _lv_img_decoder_t {
lv_img_decoder_info_f_t info_cb;
lv_img_decoder_open_f_t open_cb;
lv_img_decoder_read_line_f_t read_line_cb;
lv_img_decoder_close_f_t close_cb;
#if LV_USE_USER_DATA
void * user_data;
#endif
} lv_img_decoder_t;
/**Describe an image decoding session. Stores data about the decoding*/
typedef struct _lv_img_decoder_dsc_t {
/**The decoder which was able to open the image source*/
lv_img_decoder_t * decoder;
/**The image source. A file path like "S:my_img.png" or pointer to an `lv_img_dsc_t` variable*/
const void * src;
/**Color to draw the image. USed when the image has alpha channel only*/
lv_color_t color;
/**Frame of the image, using with animated images*/
int32_t frame_id;
/**Type of the source: file or variable. Can be set in `open` function if required*/
lv_img_src_t src_type;
/**Info about the opened image: color format, size, etc. MUST be set in `open` function*/
lv_img_header_t header;
/** Pointer to a buffer where the image's data (pixels) are stored in a decoded, plain format.
* MUST be set in `open` function*/
const uint8_t * img_data;
/** How much time did it take to open the image. [ms]
* If not set `lv_img_cache` will measure and set the time to open*/
uint32_t time_to_open;
/**A text to display instead of the image when the image can't be opened.
* Can be set in `open` function or set NULL.*/
const char * error_msg;
/**Store any custom data here is required*/
void * user_data;
#ifdef FAST_SCR_BUFFER
uint32_t img_data_size;
#endif
} lv_img_decoder_dsc_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize the image decoder module
*/
void _lv_img_decoder_init(void);
/**
* Get information about an image.
* Try the created image decoder one by one. Once one is able to get info that info will be used.
* @param src the image source. Can be
* 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_drv_register()`)
* 2) Variable: Pointer to an `lv_img_dsc_t` variable
* 3) Symbol: E.g. `LV_SYMBOL_OK`
* @param header the image info will be stored here
* @return LV_RES_OK: success; LV_RES_INV: wasn't able to get info about the image
*/
lv_res_t lv_img_decoder_get_info(const void * src, lv_img_header_t * header);
/**
* Open an image.
* Try the created image decoders one by one. Once one is able to open the image that decoder is saved in `dsc`
* @param dsc describes a decoding session. Simply a pointer to an `lv_img_decoder_dsc_t` variable.
* @param src the image source. Can be
* 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_drv_register())`)
* 2) Variable: Pointer to an `lv_img_dsc_t` variable
* 3) Symbol: E.g. `LV_SYMBOL_OK`
* @param color The color of the image with `LV_IMG_CF_ALPHA_...`
* @param frame_id the index of the frame. Used only with animated images, set 0 for normal images
* @return LV_RES_OK: opened the image. `dsc->img_data` and `dsc->header` are set.
* LV_RES_INV: none of the registered image decoders were able to open the image.
*/
lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_color_t color, int32_t frame_id);
/**
* Read a line from an opened image
* @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open`
* @param x start X coordinate (from left)
* @param y start Y coordinate (from top)
* @param len number of pixels to read
* @param buf store the data here
* @return LV_RES_OK: success; LV_RES_INV: an error occurred
*/
lv_res_t lv_img_decoder_read_line(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_coord_t len,
uint8_t * buf);
/**
* Close a decoding session
* @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open`
*/
void lv_img_decoder_close(lv_img_decoder_dsc_t * dsc);
/**
* Create a new image decoder
* @return pointer to the new image decoder
*/
lv_img_decoder_t * lv_img_decoder_create(void);
/**
* Delete an image decoder
* @param decoder pointer to an image decoder
*/
void lv_img_decoder_delete(lv_img_decoder_t * decoder);
/**
* Set a callback to get information about the image
* @param decoder pointer to an image decoder
* @param info_cb a function to collect info about an image (fill an `lv_img_header_t` struct)
*/
void lv_img_decoder_set_info_cb(lv_img_decoder_t * decoder, lv_img_decoder_info_f_t info_cb);
/**
* Set a callback to open an image
* @param decoder pointer to an image decoder
* @param open_cb a function to open an image
*/
void lv_img_decoder_set_open_cb(lv_img_decoder_t * decoder, lv_img_decoder_open_f_t open_cb);
/**
* Set a callback to a decoded line of an image
* @param decoder pointer to an image decoder
* @param read_line_cb a function to read a line of an image
*/
void lv_img_decoder_set_read_line_cb(lv_img_decoder_t * decoder, lv_img_decoder_read_line_f_t read_line_cb);
/**
* Set a callback to close a decoding session. E.g. close files and free other resources.
* @param decoder pointer to an image decoder
* @param close_cb a function to close a decoding session
*/
void lv_img_decoder_set_close_cb(lv_img_decoder_t * decoder, lv_img_decoder_close_f_t close_cb);
/**
* Get info about a built-in image
* @param decoder the decoder where this function belongs
* @param src the image source: pointer to an `lv_img_dsc_t` variable, a file path or a symbol
* @param header store the image data here
* @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error.
*/
lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header);
/**
* Open a built in image
* @param decoder the decoder where this function belongs
* @param dsc pointer to decoder descriptor. `src`, `style` are already initialized in it.
* @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error.
*/
lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc);
/**
* Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`.
* Required only if the "open" function can't return with the whole decoded pixel array.
* @param decoder pointer to the decoder the function associated with
* @param dsc pointer to decoder descriptor
* @param x start x coordinate
* @param y start y coordinate
* @param len number of pixels to decode
* @param buf a buffer to store the decoded pixels
* @return LV_RES_OK: ok; LV_RES_INV: failed
*/
lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x,
lv_coord_t y, lv_coord_t len, uint8_t * buf);
/**
* Close the pending decoding. Free resources etc.
* @param decoder pointer to the decoder the function associated with
* @param dsc pointer to decoder descriptor
*/
void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_IMG_DECODER_H*/

Binary file not shown.

View File

@ -0,0 +1,7 @@
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp"
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp/lv_draw_nxp_pxp.mk
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite/lv_draw_nxp_vglite.mk

View File

@ -0,0 +1,9 @@
CSRCS += lv_draw_pxp.c
CSRCS += lv_draw_pxp_blend.c
CSRCS += lv_gpu_nxp_pxp_osa.c
CSRCS += lv_gpu_nxp_pxp.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp"

View File

@ -0,0 +1,72 @@
/**
* @file lv_draw_pxp.h
*
*/
/**
* MIT License
*
* Copyright 2022, 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef LV_DRAW_PXP_H
#define LV_DRAW_PXP_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_PXP
#include "../../sw/lv_draw_sw.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef lv_draw_sw_ctx_t lv_draw_pxp_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_pxp_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_pxp_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_NXP_PXP*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_PXP_H*/

View File

@ -0,0 +1,116 @@
/**
* @file lv_draw_pxp_blend.h
*
*/
/**
* MIT License
*
* Copyright 2020-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef LV_DRAW_PXP_BLEND_H
#define LV_DRAW_PXP_BLEND_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_PXP
#include "lv_gpu_nxp_pxp.h"
#include "../../sw/lv_draw_sw.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Fill area, with optional opacity.
*
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] color Color
* @param[in] opa Opacity
*/
void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
lv_color_t color, lv_opa_t opa);
/**
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects.
* By default, image is copied directly, with optional opacity. This function can also
* rotate the display output buffer to a specified angle (90x step).
*
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Source area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] opa Opacity
* @param[in] angle Display rotation angle (90x)
*/
void lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
lv_opa_t opa, lv_disp_rot_t angle);
/**
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with transformation.
*
*
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] dsc Image descriptor
* @param[in] cf Color format
*/
void lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_NXP_PXP*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_PXP_BLEND_H*/

View File

@ -0,0 +1,166 @@
/**
* @file lv_gpu_nxp_pxp.h
*
*/
/**
* MIT License
*
* Copyright 2020-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef LV_GPU_NXP_PXP_H
#define LV_GPU_NXP_PXP_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_PXP
#include "fsl_cache.h"
#include "fsl_pxp.h"
#include "../../../misc/lv_log.h"
/*********************
* DEFINES
*********************/
/** PXP module instance to use*/
#define LV_GPU_NXP_PXP_ID PXP
/** PXP interrupt line ID*/
#define LV_GPU_NXP_PXP_IRQ_ID PXP_IRQn
#ifndef LV_GPU_NXP_PXP_LOG_ERRORS
/** Enable logging of PXP errors (\see LV_LOG_ERROR)*/
#define LV_GPU_NXP_PXP_LOG_ERRORS 1
#endif
#ifndef LV_GPU_NXP_PXP_LOG_TRACES
/** Enable logging of PXP errors (\see LV_LOG_ERROR)*/
#define LV_GPU_NXP_PXP_LOG_TRACES 0
#endif
/**********************
* TYPEDEFS
**********************/
/**
* NXP PXP device configuration - call-backs used for
* interrupt init/wait/deinit.
*/
typedef struct {
/** Callback for PXP interrupt initialization*/
lv_res_t (*pxp_interrupt_init)(void);
/** Callback for PXP interrupt de-initialization*/
void (*pxp_interrupt_deinit)(void);
/** Callback for PXP start*/
void (*pxp_run)(void);
/** Callback for waiting of PXP completion*/
void (*pxp_wait)(void);
} lv_nxp_pxp_cfg_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Reset and initialize PXP device. This function should be called as a part
* of display init sequence.
*
* @retval LV_RES_OK PXP init completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
*/
lv_res_t lv_gpu_nxp_pxp_init(void);
/**
* Disable PXP device. Should be called during display deinit sequence.
*/
void lv_gpu_nxp_pxp_deinit(void);
/**
* Reset PXP device.
*/
void lv_gpu_nxp_pxp_reset(void);
/**
* Clear cache and start PXP.
*/
void lv_gpu_nxp_pxp_run(void);
/**
* Wait for PXP completion.
*/
void lv_gpu_nxp_pxp_wait(void);
/**********************
* MACROS
**********************/
#define PXP_COND_STOP(cond, txt) \
do { \
if (cond) { \
LV_LOG_ERROR("%s. STOP!", txt); \
for ( ; ; ); \
} \
} while(0)
#if LV_GPU_NXP_PXP_LOG_ERRORS
#define PXP_RETURN_INV(fmt, ...) \
do { \
LV_LOG_ERROR(fmt, ##__VA_ARGS__); \
return LV_RES_INV; \
} while (0)
#else
#define PXP_RETURN_INV(fmt, ...) \
do { \
return LV_RES_INV; \
}while(0)
#endif /*LV_GPU_NXP_PXP_LOG_ERRORS*/
#if LV_GPU_NXP_PXP_LOG_TRACES
#define PXP_LOG_TRACE(fmt, ...) \
do { \
LV_LOG_ERROR(fmt, ##__VA_ARGS__); \
} while (0)
#else
#define PXP_LOG_TRACE(fmt, ...) \
do { \
} while (0)
#endif /*LV_GPU_NXP_PXP_LOG_TRACES*/
#endif /*LV_USE_GPU_NXP_PXP*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_GPU_NXP_PXP_H*/

View File

@ -0,0 +1,78 @@
/**
* @file lv_gpu_nxp_pxp_osa.h
*
*/
/**
* MIT License
*
* Copyright 2020, 2022 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef LV_GPU_NXP_PXP_OSA_H
#define LV_GPU_NXP_PXP_OSA_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT
#include "lv_gpu_nxp_pxp.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* PXP device interrupt handler. Used to check PXP task completion status.
*/
void PXP_IRQHandler(void);
/**
* Helper function to get the PXP default configuration.
*/
lv_nxp_pxp_cfg_t * lv_gpu_nxp_pxp_get_cfg(void);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_GPU_NXP_PXP_OSA_H*/

View File

@ -0,0 +1,12 @@
CSRCS += lv_draw_vglite.c
CSRCS += lv_draw_vglite_arc.c
CSRCS += lv_draw_vglite_blend.c
CSRCS += lv_draw_vglite_line.c
CSRCS += lv_draw_vglite_rect.c
CSRCS += lv_vglite_buf.c
CSRCS += lv_vglite_utils.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite"

View File

@ -0,0 +1,72 @@
/**
* @file lv_draw_vglite.h
*
*/
/**
* MIT License
*
* Copyright 2022, 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef LV_DRAW_VGLITE_H
#define LV_DRAW_VGLITE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "../../sw/lv_draw_sw.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef lv_draw_sw_ctx_t lv_draw_vglite_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_vglite_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_vglite_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_NXP_VG_LITE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_VGLITE_H*/

View File

@ -0,0 +1,83 @@
/**
* @file lv_draw_vglite_arc.h
*
*/
/**
* MIT License
*
* Copyright 2021-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef LV_DRAW_VGLITE_ARC_H
#define LV_DRAW_VGLITE_ARC_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "lv_vglite_utils.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Draw arc shape with effects
*
* @param[in] center Arc center with relative coordinates
* @param[in] radius Radius of external arc
* @param[in] start_angle Starting angle in degrees
* @param[in] end_angle Ending angle in degrees
* @param[in] clip_area Clipping area with relative coordinates to dest buff
* @param[in] dsc Arc description structure (width, rounded ending, opacity)
*
* @retval LV_RES_OK Draw completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_gpu_nxp_vglite_draw_arc(const lv_point_t * center, int32_t radius, int32_t start_angle, int32_t end_angle,
const lv_area_t * clip_area, const lv_draw_arc_dsc_t * dsc);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_NXP_VG_LITE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_VGLITE_ARC_H*/

View File

@ -0,0 +1,118 @@
/**
* @file lv_draw_vglite_blend.h
*
*/
/**
* MIT License
*
* Copyright 2020-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef LV_DRAW_VGLITE_BLEND_H
#define LV_DRAW_VGLITE_BLEND_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "lv_vglite_utils.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Fill area, with optional opacity.
*
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] color Color
* @param[in] opa Opacity (255 = full, 128 = 50% background/50% color, 0 = no fill)
*
* @retval LV_RES_OK Fill completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_gpu_nxp_vglite_fill(const lv_area_t * dest_area, lv_color_t color, lv_opa_t opa);
/**
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects.
* By default, image is copied directly, with optional opacity.
*
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Source area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] opa Opacity
*
* @retval LV_RES_OK Transfer complete
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_gpu_nxp_vglite_blit(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride,
lv_opa_t opa);
/**
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with transformation.
* By default, image is copied directly, with optional opacity.
*
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Source area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] dsc Image descriptor
*
* @retval LV_RES_OK Transfer complete
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_gpu_nxp_vglite_blit_transform(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_NXP_VG_LITE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_VGLITE_BLEND_H*/

View File

@ -0,0 +1,83 @@
/**
* @file lv_draw_vglite_line.h
*
*/
/**
* MIT License
*
* Copyright 2022, 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef LV_DRAW_VGLITE_LINE_H
#define LV_DRAW_VGLITE_LINE_H
#ifdef __cplusplus
extern "C"
{
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "lv_vglite_utils.h"
#include "../../lv_draw_line.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Draw line shape with effects
*
* @param[in] point1 Starting point with relative coordinates
* @param[in] point2 Ending point with relative coordinates
* @param[in] clip_area Clipping area with relative coordinates to dest buff
* @param[in] dsc Line description structure (width, rounded ending, opacity, ...)
*
* @retval LV_RES_OK Draw completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_gpu_nxp_vglite_draw_line(const lv_point_t * point1, const lv_point_t * point2,
const lv_area_t * clip_area, const lv_draw_line_dsc_t * dsc);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_NXP_VG_LITE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_VGLITE_RECT_H*/

View File

@ -0,0 +1,97 @@
/**
* @file lv_draw_vglite_rect.h
*
*/
/**
* MIT License
*
* Copyright 2021-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef LV_DRAW_VGLITE_RECT_H
#define LV_DRAW_VGLITE_RECT_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "lv_vglite_utils.h"
#include "../../lv_draw_rect.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Draw rectangle background with effects (rounded corners, gradient)
*
* @param[in] coords Coordinates of the rectangle background (relative to dest buff)
* @param[in] clip_area Clipping area with relative coordinates to dest buff
* @param[in] dsc Description of the rectangle background
*
* @retval LV_RES_OK Draw completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*
*/
lv_res_t lv_gpu_nxp_vglite_draw_bg(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_rect_dsc_t * dsc);
/**
* Draw rectangle border/outline shape with effects (rounded corners, opacity)
*
* @param[in] coords Coordinates of the rectangle border/outline (relative to dest buff)
* @param[in] clip_area Clipping area with relative coordinates to dest buff
* @param[in] dsc Description of the rectangle border/outline
* @param[in] border True for border, False for outline
*
* @retval LV_RES_OK Draw completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*
*/
lv_res_t lv_gpu_nxp_vglite_draw_border_generic(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_rect_dsc_t * dsc, bool border);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_NXP_VG_LITE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_VGLITE_RECT_H*/

View File

@ -0,0 +1,113 @@
/**
* @file lv_vglite_buf.h
*
*/
/**
* MIT License
*
* Copyright 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef LV_VGLITE_BUF_H
#define LV_VGLITE_BUF_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "vg_lite.h"
#include "../../sw/lv_draw_sw.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Init vglite destination buffer. It will be done once per frame.
*
* @param[in] buf Destination buffer address (does not require alignment for VG_LITE_LINEAR mode)
* @param[in] area Destination buffer area (for width and height)
* @param[in] stride Stride of destination buffer
*/
void lv_gpu_nxp_vglite_init_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride);
/**
* Get vglite destination buffer pointer.
*
* @retval The vglite destination buffer
*/
vg_lite_buffer_t * lv_vglite_get_dest_buf(void);
/**
* Get vglite source buffer pointer.
*
* @retval The vglite source buffer
*/
vg_lite_buffer_t * lv_vglite_get_src_buf(void);
/**
* Set vglite destination buffer address only.
*
* @param[in] buf Destination buffer address (does not require alignment for VG_LITE_LINEAR mode)
*/
void lv_vglite_set_dest_buf_ptr(const lv_color_t * buf);
/**
* Set vglite source buffer address only.
*
* @param[in] buf Source buffer address
*/
void lv_vglite_set_src_buf_ptr(const lv_color_t * buf);
/**
* Set vglite source buffer. It will be done only if buffer addreess is different.
*
* @param[in] buf Source buffer address
* @param[in] area Source buffer area (for width and height)
* @param[in] stride Stride of source buffer
*/
void lv_vglite_set_src_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_NXP_VG_LITE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_VGLITE_BUF_H*/

View File

@ -0,0 +1,166 @@
/**
* @file lv_vglite_utils.h
*
*/
/**
* MIT License
*
* Copyright 2022, 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef LV_VGLITE_UTILS_H
#define LV_VGLITE_UTILS_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "vg_lite.h"
#include "../../sw/lv_draw_sw.h"
#include "../../../misc/lv_log.h"
/*********************
* DEFINES
*********************/
#ifndef LV_GPU_NXP_VG_LITE_LOG_ERRORS
/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR)*/
#define LV_GPU_NXP_VG_LITE_LOG_ERRORS 1
#endif
#ifndef LV_GPU_NXP_VG_LITE_LOG_TRACES
/** Enable logging of VG-Lite traces (\see LV_LOG_ERROR)*/
#define LV_GPU_NXP_VG_LITE_LOG_TRACES 0
#endif
/* The optimal Bezier control point offset for radial unit
* see: https://spencermortensen.com/articles/bezier-circle/
**/
#define BEZIER_OPTIM_CIRCLE 0.551915024494f
/* Draw lines for control points of Bezier curves */
#define BEZIER_DBG_CONTROL_POINTS 0
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Premultiplies and swizzles given LVGL 32bit color to obtain vglite color.
*
* @param[in/out] vg_col32 The obtained vglite color
* @param[in] lv_col32 The initial LVGL 32bit color
* @param[in] opa The opacity to premultiply with
* @param[in] vg_col_format The format of the resulting vglite color
*
* @retval LV_RES_OK Operation completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_vglite_premult_and_swizzle(vg_lite_color_t * vg_col32, lv_color32_t lv_col32, lv_opa_t opa,
vg_lite_buffer_format_t vg_col_format);
/**
* Get vglite blend mode.
*
* @param[in] lv_blend_mode The LVGL blend mode
*
* @retval The vglite blend mode
*/
vg_lite_blend_t lv_vglite_get_blend_mode(lv_blend_mode_t lv_blend_mode);
/**
* Clear cache and flush command to VG-Lite.
*
* @retval LV_RES_OK Run completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_vglite_run(void);
/**********************
* MACROS
**********************/
#define VG_LITE_COND_STOP(cond, txt) \
do { \
if (cond) { \
LV_LOG_ERROR("%s. STOP!", txt); \
for ( ; ; ); \
} \
} while(0)
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
#define VG_LITE_ERR_RETURN_INV(err, fmt, ...) \
do { \
if(err != VG_LITE_SUCCESS) { \
LV_LOG_ERROR(fmt" (err = %d)", \
err, ##__VA_ARGS__); \
return LV_RES_INV; \
} \
} while (0)
#else
#define VG_LITE_ERR_RETURN_INV(err, fmt, ...) \
do { \
if(err != VG_LITE_SUCCESS) { \
return LV_RES_INV; \
} \
}while(0)
#endif /*LV_GPU_NXP_VG_LITE_LOG_ERRORS*/
#if LV_GPU_NXP_VG_LITE_LOG_TRACES
#define VG_LITE_LOG_TRACE(fmt, ...) \
do { \
LV_LOG(fmt, ##__VA_ARGS__); \
} while (0)
#define VG_LITE_RETURN_INV(fmt, ...) \
do { \
LV_LOG_ERROR(fmt, ##__VA_ARGS__); \
return LV_RES_INV; \
} while (0)
#else
#define VG_LITE_LOG_TRACE(fmt, ...) \
do { \
} while (0)
#define VG_LITE_RETURN_INV(fmt, ...) \
do { \
return LV_RES_INV; \
}while(0)
#endif /*LV_GPU_NXP_VG_LITE_LOG_TRACES*/
#endif /*LV_USE_GPU_NXP_VG_LITE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_VGLITE_UTILS_H*/

View File

@ -0,0 +1,28 @@
# SDL_Renderer Based Drawing Functions
In LVGL, drawing was performed by CPU. To improve drawing performance on platforms with GPU,
we should perform drawing operations on GPU if possible.
This implementation has moved most bitmap blending and drawing procedures to utilize SDL_Renderer,
which takes advantages of hardware acceleration APIs like DirectX or OpenGL.
This implementation can be also considered as a reference implementation, for contributors wants to
develop accelerated drawing functions with other APIs such as OpenGL/OpenGL ES.
## Caveats
`lv_draw_arc`, `lv_draw_line` is not enabled, due to incomplete implementation. So lines and arcs will
have significant impact to drawing performances.
Performance of this implementation still has room to improve. Or we should use more powerful APIs
such as OpenGL.
## Notices for files
### `lv_draw_sdl_stack_blur.c`
Contains modified code from [android-stackblur](https://github.com/kikoso/android-stackblur) project.
Apache License 2.0
### `lv_draw_sdl_lru.c`/`lv_draw_sdl_lru.h`
Contains modified code from [C-LRU-Cache](https://github.com/willcannings/C-LRU-Cache) project. No license defined.

View File

@ -0,0 +1,96 @@
/**
* @file lv_draw_sdl.h
*
*/
#ifndef LV_DRAW_SDL_H
#define LV_DRAW_SDL_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#if LV_USE_GPU_SDL
#include LV_GPU_SDL_INCLUDE_PATH
#include "../lv_draw.h"
#include "../../core/lv_disp.h"
/*********************
* DEFINES
*********************/
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define LV_DRAW_SDL_TEXTURE_FORMAT SDL_PIXELFORMAT_ARGB8888
#else
#define LV_DRAW_SDL_TEXTURE_FORMAT SDL_PIXELFORMAT_RGBA8888
#endif
/**********************
* TYPEDEFS
**********************/
struct lv_draw_sdl_context_internals_t;
typedef struct {
/**
* Render for display driver
*/
SDL_Renderer * renderer;
void * user_data;
} lv_draw_sdl_drv_param_t;
typedef struct {
lv_draw_ctx_t base_draw;
SDL_Renderer * renderer;
struct lv_draw_sdl_context_internals_t * internals;
} lv_draw_sdl_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_sdl_init_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx);
/**
* @brief Free caches
*
*/
void lv_draw_sdl_deinit_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx);
SDL_Texture * lv_draw_sdl_create_screen_texture(SDL_Renderer * renderer, lv_coord_t hor, lv_coord_t ver);
/*======================
* Add/remove functions
*=====================*/
/*=====================
* Setter functions
*====================*/
/*=====================
* Getter functions
*====================*/
/*=====================
* Other functions
*====================*/
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_SDL*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_SDL_H*/

View File

@ -0,0 +1,19 @@
CSRCS += lv_draw_sdl.c
CSRCS += lv_draw_sdl_arc.c
CSRCS += lv_draw_sdl_bg.c
CSRCS += lv_draw_sdl_composite.c
CSRCS += lv_draw_sdl_img.c
CSRCS += lv_draw_sdl_label.c
CSRCS += lv_draw_sdl_line.c
CSRCS += lv_draw_sdl_mask.c
CSRCS += lv_draw_sdl_polygon.c
CSRCS += lv_draw_sdl_rect.c
CSRCS += lv_draw_sdl_stack_blur.c
CSRCS += lv_draw_sdl_texture_cache.c
CSRCS += lv_draw_sdl_utils.c
CSRCS += lv_draw_sdl_layer.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl"

View File

@ -0,0 +1,73 @@
/**
* @file lv_draw_sdl_composite.h
*
*/
#ifndef LV_DRAW_SDL_COMPOSITE_H
#define LV_DRAW_SDL_COMPOSITE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#include LV_GPU_SDL_INCLUDE_PATH
#include "lv_draw_sdl.h"
#include "../../misc/lv_area.h"
#include "../../misc/lv_color.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef enum lv_draw_sdl_composite_texture_id_t {
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM0,
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1,
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0,
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET1,
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0,
} lv_draw_sdl_composite_texture_id_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Begin drawing with mask. Render target will be switched to a temporary texture,
* and drawing coordinates may get clipped or translated
* @param coords_in Original coordinates
* @param clip_in Original clip area
* @param extension Useful for shadows or outlines, can be NULL
* @param coords_out Translated coords
* @param clip_out Translated clip area
* @param apply_area Area of actual composited texture will be drawn
* @return true if there are any mask needs to be drawn, false otherwise
*/
bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords_in, const lv_area_t * clip_in,
const lv_area_t * extension, lv_blend_mode_t blend_mode, lv_area_t * coords_out,
lv_area_t * clip_out, lv_area_t * apply_area);
void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_area, lv_blend_mode_t blend_mode);
SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_composite_texture_id_t id,
lv_coord_t w, lv_coord_t h);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_SDL_COMPOSITE_H*/

View File

@ -0,0 +1,72 @@
/**
* @file lv_draw_sdl_img.h
*
*/
#ifndef LV_DRAW_SDL_IMG_H
#define LV_DRAW_SDL_IMG_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#if LV_USE_GPU_SDL
#include LV_GPU_SDL_INCLUDE_PATH
#include "../lv_draw.h"
#include "lv_draw_sdl_texture_cache.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct lv_draw_sdl_img_header_t {
lv_img_header_t base;
SDL_Rect rect;
} lv_draw_sdl_img_header_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/*======================
* Add/remove functions
*=====================*/
/*=====================
* Setter functions
*====================*/
/*=====================
* Getter functions
*====================*/
/*=====================
* Other functions
*====================*/
bool lv_draw_sdl_img_load_texture(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_cache_key_head_img_t * key, size_t key_size,
const void * src, int32_t frame_id, SDL_Texture ** texture,
lv_draw_sdl_img_header_t ** header);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_SDL*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_SDL_IMG_H*/

View File

@ -0,0 +1,55 @@
/**
* @file lv_draw_sdl_refr.h
*
*/
#ifndef LV_TEMPL_H
#define LV_TEMPL_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw_sdl.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct _lv_draw_sdl_layer_ctx_t {
lv_draw_layer_ctx_t base;
SDL_Texture * orig_target;
SDL_Texture * target;
SDL_Rect target_rect;
lv_draw_layer_flags_t flags;
} lv_draw_sdl_layer_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
lv_draw_layer_ctx_t * lv_draw_sdl_layer_init(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx,
lv_draw_layer_flags_t flags);
void lv_draw_sdl_layer_blend(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * transform_ctx,
const lv_draw_img_dsc_t * draw_dsc);
void lv_draw_sdl_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx);
void lv_draw_sdl_transform_areas_offset(lv_draw_sdl_ctx_t * ctx, bool has_composite, lv_area_t * apply_area,
lv_area_t * coords, lv_area_t * clip);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_TEMPL_H*/

View File

@ -0,0 +1,51 @@
/**
* @file lv_draw_sdl_mask.h
*
*/
#ifndef LV_DRAW_SDL_MASK_H
#define LV_DRAW_SDL_MASK_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#include LV_GPU_SDL_INCLUDE_PATH
#include "lv_draw_sdl.h"
#include "../../misc/lv_area.h"
#include "../../misc/lv_color.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
lv_opa_t * lv_draw_sdl_mask_dump_opa(const lv_area_t * coords, const int16_t * ids, int16_t ids_count);
SDL_Texture * lv_draw_sdl_mask_dump_texture(SDL_Renderer * renderer, const lv_area_t * coords, const int16_t * ids,
int16_t ids_count);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_SDL_MASK_H*/

View File

@ -0,0 +1,72 @@
/**
* @file lv_draw_sdl_priv.h
*
*/
#ifndef LV_DRAW_SDL_PRIV_H
#define LV_DRAW_SDL_PRIV_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#if LV_USE_GPU_SDL
#include LV_GPU_SDL_INCLUDE_PATH
#include "../lv_draw.h"
#include "../../misc/lv_lru.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct lv_draw_sdl_context_internals_t {
lv_lru_t * texture_cache;
SDL_Texture * mask;
SDL_Texture * composition;
SDL_Texture * target_backup;
uint8_t transform_count;
} lv_draw_sdl_context_internals_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/*======================
* Add/remove functions
*=====================*/
/*=====================
* Setter functions
*====================*/
/*=====================
* Getter functions
*====================*/
/*=====================
* Other functions
*====================*/
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_SDL*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_SDL_PRIV_H*/

View File

@ -0,0 +1,80 @@
/**
* @file lv_draw_sdl_rect.h
*
*/
#ifndef LV_DRAW_SDL_RECT_H
#define LV_DRAW_SDL_RECT_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#if LV_USE_GPU_SDL
#include LV_GPU_SDL_INCLUDE_PATH
#include "../lv_draw.h"
#include "lv_draw_sdl_texture_cache.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct lv_draw_sdl_rect_header_t {
lv_img_header_t base;
SDL_Rect rect;
} lv_draw_sdl_rect_header_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/*======================
* Add/remove functions
*=====================*/
/*=====================
* Setter functions
*====================*/
/*=====================
* Getter functions
*====================*/
/*=====================
* Other functions
*====================*/
SDL_Texture * lv_draw_sdl_rect_bg_frag_obtain(lv_draw_sdl_ctx_t * ctx, lv_coord_t radius);
SDL_Texture * lv_draw_sdl_rect_grad_frag_obtain(lv_draw_sdl_ctx_t * ctx, const lv_grad_dsc_t * grad, lv_coord_t w,
lv_coord_t h, lv_coord_t radius);
SDL_Texture * lv_draw_sdl_rect_grad_strip_obtain(lv_draw_sdl_ctx_t * ctx, const lv_grad_dsc_t * grad);
void lv_draw_sdl_rect_bg_frag_draw_corners(lv_draw_sdl_ctx_t * ctx, SDL_Texture * frag, lv_coord_t frag_size,
const lv_area_t * coords, const lv_area_t * clip, bool full);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_SDL*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_SDL_RECT_H*/

View File

@ -0,0 +1,46 @@
/**
* @file lv_draw_sdl_stack_blur.h
*
*/
#ifndef LV_DRAW_SDL_STACK_BLUR_H
#define LV_DRAW_SDL_STACK_BLUR_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#if LV_USE_GPU_SDL
#include "../../misc/lv_color.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_stack_blur_grayscale(lv_opa_t * buf, uint16_t w, uint16_t h, uint16_t r);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_SDL*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_SDL_STACK_BLUR_H*/

View File

@ -0,0 +1,103 @@
/**
* @file lv_draw_sdl_texture_cache.h
*
*/
#ifndef LV_DRAW_SDL_TEXTURE_CACHE_H
#define LV_DRAW_SDL_TEXTURE_CACHE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#if LV_USE_GPU_SDL
#include LV_GPU_SDL_INCLUDE_PATH
#include "lv_draw_sdl.h"
#include "lv_draw_sdl_priv.h"
#include "../../draw/lv_img_decoder.h"
#include "../../misc/lv_area.h"
/*********************
* DEFINES
*********************/
#define LV_DRAW_SDL_DEC_DSC_TEXTURE_HEAD "@LVSDLTex"
/**********************
* TYPEDEFS
**********************/
typedef struct {
char head[8];
SDL_Texture * texture;
SDL_Rect rect;
bool texture_managed;
bool texture_referenced;
} lv_draw_sdl_dec_dsc_userdata_t;
typedef enum {
LV_GPU_CACHE_KEY_MAGIC_ARC = 0x01,
LV_GPU_CACHE_KEY_MAGIC_IMG = 0x11,
LV_GPU_CACHE_KEY_MAGIC_IMG_ROUNDED_CORNERS = 0x12,
LV_GPU_CACHE_KEY_MAGIC_LINE = 0x21,
LV_GPU_CACHE_KEY_MAGIC_RECT_BG = 0x31,
LV_GPU_CACHE_KEY_MAGIC_RECT_SHADOW = 0x32,
LV_GPU_CACHE_KEY_MAGIC_RECT_BORDER = 0x33,
LV_GPU_CACHE_KEY_MAGIC_RECT_GRAD = 0x34,
LV_GPU_CACHE_KEY_MAGIC_FONT_GLYPH = 0x41,
LV_GPU_CACHE_KEY_MAGIC_MASK = 0x51,
} lv_sdl_cache_key_magic_t;
typedef enum {
LV_DRAW_SDL_CACHE_FLAG_NONE = 0,
LV_DRAW_SDL_CACHE_FLAG_MANAGED = 1,
} lv_draw_sdl_cache_flag_t;
typedef struct {
lv_sdl_cache_key_magic_t magic;
lv_img_src_t type;
int32_t frame_id;
} lv_draw_sdl_cache_key_head_img_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_sdl_texture_cache_init(lv_draw_sdl_ctx_t * ctx);
void lv_draw_sdl_texture_cache_deinit(lv_draw_sdl_ctx_t * ctx);
/**
* Find cached texture by key. The texture can be destroyed during usage.
*/
SDL_Texture * lv_draw_sdl_texture_cache_get(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, bool * found);
SDL_Texture * lv_draw_sdl_texture_cache_get_with_userdata(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
bool * found, void ** userdata);
void lv_draw_sdl_texture_cache_put(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, SDL_Texture * texture);
void lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
SDL_Texture * texture, void * userdata, void userdata_free(void *),
lv_draw_sdl_cache_flag_t flags);
lv_draw_sdl_cache_key_head_img_t * lv_draw_sdl_texture_img_key_create(const void * src, int32_t frame_id,
size_t * size);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_SDL*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_SDL_TEXTURE_CACHE_H*/

View File

@ -0,0 +1,65 @@
/**
* @file lv_draw_sdl_utils.h
*
*/
#ifndef LV_DRAW_SDL_UTILS_H
#define LV_DRAW_SDL_UTILS_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#if LV_USE_GPU_SDL
#include "lv_draw_sdl.h"
#include "../../misc/lv_color.h"
#include "../../misc/lv_area.h"
#include LV_GPU_SDL_INCLUDE_PATH
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void _lv_draw_sdl_utils_init();
void _lv_draw_sdl_utils_deinit();
void lv_area_to_sdl_rect(const lv_area_t * in, SDL_Rect * out);
void lv_color_to_sdl_color(const lv_color_t * in, SDL_Color * out);
void lv_area_zoom_to_sdl_rect(const lv_area_t * in, SDL_Rect * out, uint16_t zoom, const lv_point_t * pivot);
SDL_Palette * lv_sdl_alloc_palette_for_bpp(const uint8_t * mapping, uint8_t bpp);
SDL_Surface * lv_sdl_create_opa_surface(lv_opa_t * opa, lv_coord_t width, lv_coord_t height, lv_coord_t stride);
SDL_Texture * lv_sdl_create_opa_texture(SDL_Renderer * renderer, lv_opa_t * pixels, lv_coord_t width,
lv_coord_t height, lv_coord_t stride);
void lv_sdl_to_8bpp(uint8_t * dest, const uint8_t * src, int width, int height, int stride, uint8_t bpp);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_SDL*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_SDL_UTILS_H*/

View File

@ -0,0 +1,6 @@
CSRCS += lv_gpu_stm32_dma2d.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d"

View File

@ -0,0 +1,101 @@
/**
* @file lv_gpu_stm32_dma2d.h
*
*/
#ifndef LV_GPU_STM32_DMA2D_H
#define LV_GPU_STM32_DMA2D_H
#ifdef __cplusplus
extern "C" {
#endif
#include "../../misc/lv_color.h"
#include "../../hal/lv_hal_disp.h"
#include "../sw/lv_draw_sw.h"
#if LV_USE_GPU_STM32_DMA2D
/*********************
* INCLUDES
*********************/
#include LV_GPU_DMA2D_CMSIS_INCLUDE
/*********************
* DEFINES
*********************/
#if defined(LV_STM32_DMA2D_TEST)
// removes "static" modifier for some internal methods in order to test them
#define LV_STM32_DMA2D_STATIC
#else
#define LV_STM32_DMA2D_STATIC static
#endif
/**********************
* TYPEDEFS
**********************/
enum dma2d_color_format {
ARGB8888 = 0x0,
RGB888 = 0x01,
RGB565 = 0x02,
ARGB1555 = 0x03,
ARGB4444 = 0x04,
A8 = 0x09,
UNSUPPORTED = 0xff,
};
typedef enum dma2d_color_format dma2d_color_format_t;
typedef lv_draw_sw_ctx_t lv_draw_stm32_dma2d_ctx_t;
struct _lv_disp_drv_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_stm32_dma2d_init(void);
void lv_draw_stm32_dma2d_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_stm32_dma2d_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
static void lv_draw_stm32_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
static void lv_draw_stm32_dma2d_buffer_copy(lv_draw_ctx_t * draw_ctx,
void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area,
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area);
static lv_res_t lv_draw_stm32_dma2d_img(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * img_dsc,
const lv_area_t * src_area, const void * src);
static void lv_gpu_stm32_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx);
static void lv_draw_stm32_dma2d_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * img_dsc,
const lv_area_t * coords, const uint8_t * src_buf, lv_img_cf_t color_format);
static dma2d_color_format_t lv_color_format_to_dma2d_color_format(lv_img_cf_t color_format);
static lv_point_t lv_area_get_offset(const lv_area_t * area1, const lv_area_t * area2);
/**********************
* STATIC PROTOTYPES
**********************/
LV_STM32_DMA2D_STATIC void _lv_draw_stm32_dma2d_blend_fill(const lv_color_t * dst_buf, lv_coord_t dst_stride,
const lv_area_t * draw_area, lv_color_t color, lv_opa_t opa);
LV_STM32_DMA2D_STATIC void _lv_draw_stm32_dma2d_blend_map(const lv_color_t * dest_buf, lv_coord_t dest_stride,
const lv_area_t * draw_area, const void * src_buf, lv_coord_t src_stride, const lv_point_t * src_offset, lv_opa_t opa,
dma2d_color_format_t src_color_format, bool ignore_src_alpha);
LV_STM32_DMA2D_STATIC void _lv_draw_stm32_dma2d_blend_paint(const lv_color_t * dst_buf, lv_coord_t dst_stride,
const lv_area_t * draw_area, const lv_opa_t * mask_buf, lv_coord_t mask_stride, const lv_point_t * mask_offset,
lv_color_t color, lv_opa_t opa);
LV_STM32_DMA2D_STATIC void _lv_draw_stm32_dma2d_copy_buffer(const lv_color_t * dest_buf, lv_coord_t dest_stride,
const lv_area_t * draw_area, const lv_color_t * src_buf, lv_coord_t src_stride, const lv_point_t * src_offset);
LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dma2d_await_dma_transfer_finish(lv_disp_drv_t * disp_drv);
LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dma2d_start_dma_transfer(void);
LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dma2d_invalidate_cache(uint32_t address, lv_coord_t offset,
lv_coord_t width, lv_coord_t height, uint8_t pixel_size);
LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dma2d_clean_cache(uint32_t address, lv_coord_t offset, lv_coord_t width,
lv_coord_t height, uint8_t pixel_size);
LV_STM32_DMA2D_STATIC bool _lv_gpu_stm32_dwt_init(void);
LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dwt_reset(void);
LV_STM32_DMA2D_STATIC uint32_t _lv_gpu_stm32_dwt_get_us(void);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_STM32_DMA2D*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_GPU_STM32_DMA2D_H*/

View File

@ -0,0 +1,127 @@
/**
* @file lv_draw_sw.h
*
*/
#ifndef LV_DRAW_SW_H
#define LV_DRAW_SW_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw_sw_blend.h"
#include "../lv_draw.h"
#include "../../misc/lv_area.h"
#include "../../misc/lv_color.h"
#include "../../hal/lv_hal_disp.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct _lv_disp_drv_t;
typedef struct {
lv_draw_ctx_t base_draw;
/** Fill an area of the destination buffer with a color*/
void (*blend)(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
} lv_draw_sw_ctx_t;
typedef struct {
lv_draw_layer_ctx_t base_draw;
uint32_t buf_size_bytes: 31;
uint32_t has_alpha : 1;
} lv_draw_sw_layer_ctx_t;
#ifdef FAST_SCR_BUFFER
typedef struct {
int16_t group_id;
int16_t line_num;
int32_t src_size;
int32_t size;
int32_t offset;
uint8_t * src_addr;
} lv_psram_but_t;
#endif
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_sw_init_ctx(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_sw_deinit_ctx(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_sw_wait_for_finish(lv_draw_ctx_t * draw_ctx);
void lv_draw_sw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, uint16_t radius,
uint16_t start_angle, uint16_t end_angle);
void lv_draw_sw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
void lv_draw_sw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
void lv_draw_sw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
uint32_t letter);
#ifdef __XTENSA__
LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_img_decoded_dsp(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
const lv_area_t * coords, const uint8_t * src_buf, lv_img_cf_t cf,
uint8_t mask_any, uint32_t max_buf_size, uint32_t ck);
#else
LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_img_decoded(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
const lv_area_t * coords, const uint8_t * src_buf, lv_img_cf_t cf);
#endif
LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_line(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc,
const lv_point_t * point1, const lv_point_t * point2);
void lv_draw_sw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc,
const lv_point_t * points, uint16_t point_cnt);
void lv_draw_sw_buffer_copy(lv_draw_ctx_t * draw_ctx,
void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area,
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area);
#ifdef __XTENSA__
void lv_draw_sw_transform_dsp(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf,
lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride,
const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf, uint32_t _ck);
#else
void lv_draw_sw_transform(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf,
lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride,
const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf);
#endif
struct _lv_draw_layer_ctx_t * lv_draw_sw_layer_create(struct _lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx,
lv_draw_layer_flags_t flags);
void lv_draw_sw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
lv_draw_layer_flags_t flags);
void lv_draw_sw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
const lv_draw_img_dsc_t * draw_dsc);
void lv_draw_sw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx);
/***********************
* GLOBAL VARIABLES
***********************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_SW_H*/

View File

@ -0,0 +1,17 @@
CSRCS += lv_draw_sw.c
CSRCS += lv_draw_sw_arc.c
CSRCS += lv_draw_sw_blend.c
CSRCS += lv_draw_sw_dither.c
CSRCS += lv_draw_sw_gradient.c
CSRCS += lv_draw_sw_img.c
CSRCS += lv_draw_sw_letter.c
CSRCS += lv_draw_sw_line.c
CSRCS += lv_draw_sw_polygon.c
CSRCS += lv_draw_sw_rect.c
CSRCS += lv_draw_sw_transform.c
CSRCS += lv_draw_sw_layer.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw"

View File

@ -0,0 +1,69 @@
/**
* @file lv_draw_sw_blend.h
*
*/
#ifndef LV_DRAW_SW_BLEND_H
#define LV_DRAW_SW_BLEND_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../misc/lv_color.h"
#include "../../misc/lv_area.h"
#include "../../misc/lv_style.h"
#include "../lv_draw_mask.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
const lv_area_t * blend_area; /**< The area with absolute coordinates to draw on `draw_ctx->buf`
* will be clipped to `draw_ctx->clip_area` */
const lv_color_t * src_buf; /**< Pointer to an image to blend. If set `fill_color` is ignored */
lv_color_t color; /**< Fill color*/
lv_opa_t * mask_buf; /**< NULL if ignored, or an alpha mask to apply on `blend_area`*/
lv_draw_mask_res_t mask_res; /**< The result of the previous mask operation */
const lv_area_t * mask_area; /**< The area of `mask_buf` with absolute coordinates*/
lv_opa_t opa; /**< The overall opacity*/
lv_blend_mode_t blend_mode; /**< E.g. LV_BLEND_MODE_ADDITIVE*/
} lv_draw_sw_blend_dsc_t;
struct _lv_draw_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Call the blend function of the `draw_ctx`.
* @param draw_ctx pointer to a draw context
* @param dsc pointer to an initialized blend descriptor
*/
void lv_draw_sw_blend(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
/**
* The basic blend function used with software rendering.
* @param draw_ctx pointer to a draw context
* @param dsc pointer to an initialized blend descriptor
*/
LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_basic(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_SW_BLEND_H*/

View File

@ -0,0 +1,70 @@
/**
* @file lv_draw_sw_dither.h
*
*/
#ifndef LV_DRAW_SW_DITHER_H
#define LV_DRAW_SW_DITHER_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../core/lv_obj_pos.h"
/*********************
* DEFINES
*********************/
#if LV_COLOR_DEPTH < 32 && LV_DITHER_GRADIENT == 1
#define _DITHER_GRADIENT 1
#else
#define _DITHER_GRADIENT 0
#endif
/**********************
* TYPEDEFS
**********************/
#if _DITHER_GRADIENT
/*A signed error color component*/
typedef struct {
int8_t r, g, b;
} lv_scolor24_t;
struct _lv_gradient_cache_t;
typedef void (*lv_dither_func_t)(struct _lv_gradient_cache_t * grad, lv_coord_t x, lv_coord_t y, lv_coord_t w);
#endif
/**********************
* PROTOTYPES
**********************/
#if LV_DRAW_COMPLEX
#if _DITHER_GRADIENT
LV_ATTRIBUTE_FAST_MEM void lv_dither_none(struct _lv_gradient_cache_t * grad, lv_coord_t x, lv_coord_t y, lv_coord_t w);
LV_ATTRIBUTE_FAST_MEM void lv_dither_ordered_hor(struct _lv_gradient_cache_t * grad, const lv_coord_t xs,
const lv_coord_t y, const lv_coord_t w);
LV_ATTRIBUTE_FAST_MEM void lv_dither_ordered_ver(struct _lv_gradient_cache_t * grad, const lv_coord_t xs,
const lv_coord_t y, const lv_coord_t w);
#if LV_DITHER_ERROR_DIFFUSION == 1
LV_ATTRIBUTE_FAST_MEM void lv_dither_err_diff_hor(struct _lv_gradient_cache_t * grad, const lv_coord_t xs,
const lv_coord_t y, const lv_coord_t w);
LV_ATTRIBUTE_FAST_MEM void lv_dither_err_diff_ver(struct _lv_gradient_cache_t * grad, const lv_coord_t xs,
const lv_coord_t y, const lv_coord_t w);
#endif /* LV_DITHER_ERROR_DIFFUSION */
#endif /* _DITHER_GRADIENT */
#endif
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif

View File

@ -0,0 +1,97 @@
/**
* @file lv_draw_sw_gradient.h
*
*/
#ifndef LV_DRAW_SW_GRADIENT_H
#define LV_DRAW_SW_GRADIENT_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../misc/lv_color.h"
#include "../../misc/lv_style.h"
#include "lv_draw_sw_dither.h"
/*********************
* DEFINES
*********************/
#if LV_GRADIENT_MAX_STOPS < 2
#error LVGL needs at least 2 stops for gradients. Please increase the LV_GRADIENT_MAX_STOPS
#endif
/**********************
* TYPEDEFS
**********************/
#if _DITHER_GRADIENT
typedef lv_color32_t lv_grad_color_t;
#else
typedef lv_color_t lv_grad_color_t;
#endif
/** To avoid recomputing gradient for each draw operation,
* it's possible to cache the computation in this structure instance.
* Whenever possible, this structure is reused instead of recomputing the gradient map */
typedef struct _lv_gradient_cache_t {
uint32_t key; /**< A discriminating key that's built from the drawing operation.
* If the key does not match, the cache item is not used */
uint32_t life : 30; /**< A life counter that's incremented on usage. Higher counter is
* less likely to be evicted from the cache */
uint32_t filled : 1; /**< Used to skip dithering in it if already done */
uint32_t not_cached: 1; /**< The cache was too small so this item is not managed by the cache*/
lv_color_t * map; /**< The computed gradient low bitdepth color map, points into the
* cache's buffer, no free needed */
lv_coord_t alloc_size; /**< The map allocated size in colors */
lv_coord_t size; /**< The computed gradient color map size, in colors */
#if _DITHER_GRADIENT
lv_color32_t * hmap; /**< If dithering, we need to store the current, high bitdepth gradient
* map too, points to the cache's buffer, no free needed */
#if LV_DITHER_ERROR_DIFFUSION == 1
lv_scolor24_t * error_acc; /**< Error diffusion dithering algorithm requires storing the last error
* drawn, points to the cache's buffer, no free needed */
lv_coord_t w; /**< The error array width in pixels */
#endif
#endif
} lv_grad_t;
/**********************
* PROTOTYPES
**********************/
/** Compute the color in the given gradient and fraction
* Gradient are specified in a virtual [0-255] range, so this function scales the virtual range to the given range
* @param dsc The gradient descriptor to use
* @param range The range to use in computation.
* @param frac The current part used in the range. frac is in [0; range]
*/
LV_ATTRIBUTE_FAST_MEM lv_grad_color_t lv_gradient_calculate(const lv_grad_dsc_t * dsc, lv_coord_t range,
lv_coord_t frac);
/**
* Set the gradient cache size
* @param max_bytes Max cahce size
*/
void lv_gradient_set_cache_size(size_t max_bytes);
/** Free the gradient cache */
void lv_gradient_free_cache(void);
/** Get a gradient cache from the given parameters */
lv_grad_t * lv_gradient_get(const lv_grad_dsc_t * gradient, lv_coord_t w, lv_coord_t h);
/**
* Clean up the gradient item after it was get with `lv_grad_get_from_cache`.
* @param grad pointer to a gradient
*/
void lv_gradient_cleanup(lv_grad_t * grad);
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_GRADIENT_H*/

View File

@ -0,0 +1,6 @@
CSRCS += lv_gpu_swm341_dma2d.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/swm341_dma2d
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/swm341_dma2d
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/swm341_dma2d"

View File

@ -0,0 +1,64 @@
/**
* @file lv_gpu_swm341_dma2d.h
*
*/
#ifndef LV_GPU_SWM341_DMA2D_H
#define LV_GPU_SWM341_DMA2D_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../misc/lv_color.h"
#include "../../hal/lv_hal_disp.h"
#include "../sw/lv_draw_sw.h"
#if LV_USE_GPU_SWM341_DMA2D
/*********************
* DEFINES
*********************/
#define LV_SWM341_DMA2D_ARGB8888 0
#define LV_SWM341_DMA2D_RGB888 1
#define LV_SWM341_DMA2D_RGB565 2
/**********************
* TYPEDEFS
**********************/
typedef lv_draw_sw_ctx_t lv_draw_swm341_dma2d_ctx_t;
struct _lv_disp_drv_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Turn on the peripheral and set output color mode, this only needs to be done once
*/
void lv_draw_swm341_dma2d_init(void);
void lv_draw_swm341_dma2d_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_swm341_dma2d_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_swm341_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
void lv_gpu_swm341_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_SWM341_DMA2D*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_GPU_SWM341_DMA2D_H*/

View File

@ -0,0 +1,31 @@
# Extra components
This directory contains extra (optional) components to lvgl.
It's a good place for contributions as there are less strict expectations about the completeness and flexibility of the components here.
In other words, if you have created a complex widget from other widgets, or modified an existing widget with special events, styles or animations, or have a new feature that could work as a plugin to lvgl feel free to the share it here.
## How to contribute
- Create a [Pull request](https://docs.lvgl.io/8.0/CONTRIBUTING.html#pull-request) with your new content
- Please and follow the [Coding style](https://github.com/lvgl/lvgl/blob/master/docs/CODING_STYLE.md) of LVGL
- Add setter/getter functions in pair
- Update [lv_conf_template.h](https://github.com/lvgl/lvgl/blob/master/lv_conf_template.h)
- Add description in the [docs](https://github.com/lvgl/lvgl/tree/master/docs)
- Add [examples](https://github.com/lvgl/lvgl/tree/master/examples)
- Update the [changelog](https://github.com/lvgl/lvgl/tree/master/docs/CHANGELOG.md)
- Add yourself to the [Contributors](#contributors) section below.
## Ideas
Here some ideas as inspiration feel free to contribute with ideas too.
- New [Calendar headers](https://github.com/lvgl/lvgl/tree/master/src/extra/widgets/calendar)
- Color picker with RGB and or HSV bars
- Ruler, horizontal or vertical with major and minor ticks and labels
- New [List items types](https://github.com/lvgl/lvgl/tree/master/src/extra/widgets/list)
- [Preloaders](https://www.google.com/search?q=preloader&sxsrf=ALeKk01ddA4YB0WEgLLN1bZNSm8YER7pkg:1623080551559&source=lnms&tbm=isch&sa=X&ved=2ahUKEwiwoN6d7oXxAhVuw4sKHVedBB4Q_AUoAXoECAEQAw&biw=952&bih=940)
- Drop-down list with a container to which content can be added
- 9 patch button: Similar to [lv_imgbtn](https://docs.lvgl.io/8.0/widgets/extra/imgbtn.html) but 9 images for 4 corner, 4 sides and the center
## Contributors
- lv_animimg: @ZhaoQiang-b45475
- lv_span: @guoweilkd
- lv_menu: @HX2003

View File

@ -0,0 +1,602 @@
/**
* @file lv_flex.c
*
*/
/*********************
* INCLUDES
*********************/
#include "../lv_layouts.h"
#if LV_USE_FLEX
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_flex_align_t main_place;
lv_flex_align_t cross_place;
lv_flex_align_t track_place;
uint8_t row : 1;
uint8_t wrap : 1;
uint8_t rev : 1;
} flex_t;
typedef struct {
lv_obj_t * item;
lv_coord_t min_size;
lv_coord_t max_size;
lv_coord_t final_size;
uint32_t grow_value;
uint32_t clamped : 1;
} grow_dsc_t;
typedef struct {
lv_coord_t track_cross_size;
lv_coord_t track_main_size; /*For all items*/
lv_coord_t track_fix_main_size; /*For non grow items*/
uint32_t item_cnt;
grow_dsc_t * grow_dsc;
uint32_t grow_item_cnt;
uint32_t grow_dsc_calc : 1;
} track_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void flex_update(lv_obj_t * cont, void * user_data);
static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, lv_coord_t max_main_size,
lv_coord_t item_gap, track_t * t);
static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, int32_t item_last_id, lv_coord_t abs_x,
lv_coord_t abs_y, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t);
static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt,
lv_coord_t * start_pos, lv_coord_t * gap);
static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id);
/**********************
* GLOBAL VARIABLES
**********************/
uint16_t LV_LAYOUT_FLEX;
lv_style_prop_t LV_STYLE_FLEX_FLOW;
lv_style_prop_t LV_STYLE_FLEX_MAIN_PLACE;
lv_style_prop_t LV_STYLE_FLEX_CROSS_PLACE;
lv_style_prop_t LV_STYLE_FLEX_TRACK_PLACE;
lv_style_prop_t LV_STYLE_FLEX_GROW;
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/*=====================
* Setter functions
*====================*/
void lv_flex_init(void)
{
LV_LAYOUT_FLEX = lv_layout_register(flex_update, NULL);
LV_STYLE_FLEX_FLOW = lv_style_register_prop(LV_STYLE_PROP_FLAG_NONE);
LV_STYLE_FLEX_MAIN_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
LV_STYLE_FLEX_CROSS_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
LV_STYLE_FLEX_TRACK_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
}
void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow)
{
lv_obj_set_style_flex_flow(obj, flow, 0);
lv_obj_set_style_layout(obj, LV_LAYOUT_FLEX, 0);
}
void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place,
lv_flex_align_t track_place)
{
lv_obj_set_style_flex_main_place(obj, main_place, 0);
lv_obj_set_style_flex_cross_place(obj, cross_place, 0);
lv_obj_set_style_flex_track_place(obj, track_place, 0);
lv_obj_set_style_layout(obj, LV_LAYOUT_FLEX, 0);
}
void lv_obj_set_flex_grow(lv_obj_t * obj, uint8_t grow)
{
lv_obj_set_style_flex_grow(obj, grow, 0);
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
}
void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_style_set_prop(style, LV_STYLE_FLEX_FLOW, v);
}
void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_style_set_prop(style, LV_STYLE_FLEX_MAIN_PLACE, v);
}
void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_style_set_prop(style, LV_STYLE_FLEX_CROSS_PLACE, v);
}
void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_style_set_prop(style, LV_STYLE_FLEX_TRACK_PLACE, v);
}
void lv_style_set_flex_grow(lv_style_t * style, uint8_t value)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_style_set_prop(style, LV_STYLE_FLEX_GROW, v);
}
void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t) value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_FLOW, v, selector);
}
void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t) value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_MAIN_PLACE, v, selector);
}
void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t) value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_CROSS_PLACE, v, selector);
}
void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t) value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_TRACK_PLACE, v, selector);
}
void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t) value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_GROW, v, selector);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void flex_update(lv_obj_t * cont, void * user_data)
{
LV_LOG_INFO("update %p container", (void *)cont);
LV_UNUSED(user_data);
flex_t f;
lv_flex_flow_t flow = lv_obj_get_style_flex_flow(cont, LV_PART_MAIN);
f.row = flow & _LV_FLEX_COLUMN ? 0 : 1;
f.wrap = flow & _LV_FLEX_WRAP ? 1 : 0;
f.rev = flow & _LV_FLEX_REVERSE ? 1 : 0;
f.main_place = lv_obj_get_style_flex_main_place(cont, LV_PART_MAIN);
f.cross_place = lv_obj_get_style_flex_cross_place(cont, LV_PART_MAIN);
f.track_place = lv_obj_get_style_flex_track_place(cont, LV_PART_MAIN);
bool rtl = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false;
lv_coord_t track_gap = !f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont,
LV_PART_MAIN);
lv_coord_t item_gap = f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont,
LV_PART_MAIN);
lv_coord_t max_main_size = (f.row ? lv_obj_get_content_width(cont) : lv_obj_get_content_height(cont));
lv_coord_t border_width = lv_obj_get_style_border_width(cont, LV_PART_MAIN);
lv_coord_t abs_y = cont->coords.y1 + lv_obj_get_style_pad_top(cont,
LV_PART_MAIN) + border_width - lv_obj_get_scroll_y(cont);
lv_coord_t abs_x = cont->coords.x1 + lv_obj_get_style_pad_left(cont,
LV_PART_MAIN) + border_width - lv_obj_get_scroll_x(cont);
lv_flex_align_t track_cross_place = f.track_place;
lv_coord_t * cross_pos = (f.row ? &abs_y : &abs_x);
lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN);
lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN);
/*Content sized objects should squeezed the gap between the children, therefore any alignment will look like `START`*/
if((f.row && h_set == LV_SIZE_CONTENT && cont->h_layout == 0) ||
(!f.row && w_set == LV_SIZE_CONTENT && cont->w_layout == 0)) {
track_cross_place = LV_FLEX_ALIGN_START;
}
if(rtl && !f.row) {
if(track_cross_place == LV_FLEX_ALIGN_START) track_cross_place = LV_FLEX_ALIGN_END;
else if(track_cross_place == LV_FLEX_ALIGN_END) track_cross_place = LV_FLEX_ALIGN_START;
}
lv_coord_t total_track_cross_size = 0;
lv_coord_t gap = 0;
uint32_t track_cnt = 0;
int32_t track_first_item;
int32_t next_track_first_item;
if(track_cross_place != LV_FLEX_ALIGN_START) {
track_first_item = f.rev ? cont->spec_attr->child_cnt - 1 : 0;
track_t t;
while(track_first_item < (int32_t)cont->spec_attr->child_cnt && track_first_item >= 0) {
/*Search the first item of the next row*/
t.grow_dsc_calc = 0;
next_track_first_item = find_track_end(cont, &f, track_first_item, max_main_size, item_gap, &t);
total_track_cross_size += t.track_cross_size + track_gap;
track_cnt++;
track_first_item = next_track_first_item;
}
if(track_cnt) total_track_cross_size -= track_gap; /*No gap after the last track*/
/*Place the tracks to get the start position*/
lv_coord_t max_cross_size = (f.row ? lv_obj_get_content_height(cont) : lv_obj_get_content_width(cont));
place_content(track_cross_place, max_cross_size, total_track_cross_size, track_cnt, cross_pos, &gap);
}
track_first_item = f.rev ? cont->spec_attr->child_cnt - 1 : 0;
if(rtl && !f.row) {
*cross_pos += total_track_cross_size;
}
while(track_first_item < (int32_t)cont->spec_attr->child_cnt && track_first_item >= 0) {
track_t t;
t.grow_dsc_calc = 1;
/*Search the first item of the next row*/
next_track_first_item = find_track_end(cont, &f, track_first_item, max_main_size, item_gap, &t);
if(rtl && !f.row) {
*cross_pos -= t.track_cross_size;
}
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;
lv_mem_buf_release(t.grow_dsc);
t.grow_dsc = NULL;
if(rtl && !f.row) {
*cross_pos -= gap + track_gap;
}
else {
*cross_pos += t.track_cross_size + gap + track_gap;
}
}
LV_ASSERT_MEM_INTEGRITY();
if(w_set == LV_SIZE_CONTENT || h_set == LV_SIZE_CONTENT) {
lv_obj_refr_size(cont);
}
lv_event_send(cont, LV_EVENT_LAYOUT_CHANGED, NULL);
LV_TRACE_LAYOUT("finished");
}
/**
* Find the last item of a track
*/
static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, lv_coord_t max_main_size,
lv_coord_t item_gap, track_t * t)
{
lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN);
lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN);
/*Can't wrap if the size if auto (i.e. the size depends on the children)*/
if(f->wrap && ((f->row && w_set == LV_SIZE_CONTENT) || (!f->row && h_set == LV_SIZE_CONTENT))) {
f->wrap = false;
}
lv_coord_t(*get_main_size)(const lv_obj_t *) = (f->row ? lv_obj_get_width : lv_obj_get_height);
lv_coord_t(*get_cross_size)(const lv_obj_t *) = (!f->row ? lv_obj_get_width : lv_obj_get_height);
t->track_main_size = 0;
t->track_fix_main_size = 0;
t->grow_item_cnt = 0;
t->track_cross_size = 0;
t->item_cnt = 0;
t->grow_dsc = NULL;
int32_t item_id = item_start_id;
lv_obj_t * item = lv_obj_get_child(cont, item_id);
while(item) {
if(item_id != item_start_id && lv_obj_has_flag(item, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK)) break;
if(!lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) {
uint8_t grow_value = lv_obj_get_style_flex_grow(item, LV_PART_MAIN);
if(grow_value) {
t->grow_item_cnt++;
t->track_fix_main_size += item_gap;
if(t->grow_dsc_calc) {
grow_dsc_t * new_dsc = lv_mem_buf_get(sizeof(grow_dsc_t) * (t->grow_item_cnt));
LV_ASSERT_MALLOC(new_dsc);
if(new_dsc == NULL) return item_id;
if(t->grow_dsc) {
lv_memcpy(new_dsc, t->grow_dsc, sizeof(grow_dsc_t) * (t->grow_item_cnt - 1));
lv_mem_buf_release(t->grow_dsc);
}
new_dsc[t->grow_item_cnt - 1].item = item;
new_dsc[t->grow_item_cnt - 1].min_size = f->row ? lv_obj_get_style_min_width(item,
LV_PART_MAIN) : lv_obj_get_style_min_height(item, LV_PART_MAIN);
new_dsc[t->grow_item_cnt - 1].max_size = f->row ? lv_obj_get_style_max_width(item,
LV_PART_MAIN) : lv_obj_get_style_max_height(item, LV_PART_MAIN);
new_dsc[t->grow_item_cnt - 1].grow_value = grow_value;
new_dsc[t->grow_item_cnt - 1].clamped = 0;
t->grow_dsc = new_dsc;
}
}
else {
lv_coord_t item_size = get_main_size(item);
if(f->wrap && t->track_fix_main_size + item_size > max_main_size) break;
t->track_fix_main_size += item_size + item_gap;
}
t->track_cross_size = LV_MAX(get_cross_size(item), t->track_cross_size);
t->item_cnt++;
}
item_id += f->rev ? -1 : +1;
if(item_id < 0) break;
item = lv_obj_get_child(cont, item_id);
}
if(t->track_fix_main_size > 0) t->track_fix_main_size -= item_gap; /*There is no gap after the last item*/
/*If there is at least one "grow item" the track takes the full space*/
t->track_main_size = t->grow_item_cnt ? max_main_size : t->track_fix_main_size;
/*Have at least one item in a row*/
if(item && item_id == item_start_id) {
item = cont->spec_attr->children[item_id];
get_next_item(cont, f->rev, &item_id);
if(item) {
t->track_cross_size = get_cross_size(item);
t->track_main_size = get_main_size(item);
t->item_cnt = 1;
}
}
return item_id;
}
/**
* Position the children in the same track
*/
static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, int32_t item_last_id, lv_coord_t abs_x,
lv_coord_t abs_y, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t)
{
void (*area_set_main_size)(lv_area_t *, lv_coord_t) = (f->row ? lv_area_set_width : lv_area_set_height);
lv_coord_t (*area_get_main_size)(const lv_area_t *) = (f->row ? lv_area_get_width : lv_area_get_height);
lv_coord_t (*area_get_cross_size)(const lv_area_t *) = (!f->row ? lv_area_get_width : lv_area_get_height);
/*Calculate the size of grow items first*/
uint32_t i;
bool grow_reiterate = true;
while(grow_reiterate) {
grow_reiterate = false;
lv_coord_t grow_value_sum = 0;
lv_coord_t grow_max_size = t->track_main_size - t->track_fix_main_size;
for(i = 0; i < t->grow_item_cnt; i++) {
if(t->grow_dsc[i].clamped == 0) {
grow_value_sum += t->grow_dsc[i].grow_value;
}
else {
grow_max_size -= t->grow_dsc[i].final_size;
}
}
lv_coord_t grow_unit;
for(i = 0; i < t->grow_item_cnt; i++) {
if(t->grow_dsc[i].clamped == 0) {
LV_ASSERT(grow_value_sum != 0);
grow_unit = grow_max_size / grow_value_sum;
lv_coord_t size = grow_unit * t->grow_dsc[i].grow_value;
lv_coord_t size_clamp = LV_CLAMP(t->grow_dsc[i].min_size, size, t->grow_dsc[i].max_size);
if(size_clamp != size) {
t->grow_dsc[i].clamped = 1;
grow_reiterate = true;
}
t->grow_dsc[i].final_size = size_clamp;
grow_value_sum -= t->grow_dsc[i].grow_value;
grow_max_size -= t->grow_dsc[i].final_size;
}
}
}
bool rtl = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false;
lv_coord_t main_pos = 0;
lv_coord_t place_gap = 0;
place_content(f->main_place, max_main_size, t->track_main_size, t->item_cnt, &main_pos, &place_gap);
if(f->row && rtl) main_pos += lv_obj_get_content_width(cont);
lv_obj_t * item = lv_obj_get_child(cont, item_first_id);
/*Reposition the children*/
while(item && item_first_id != item_last_id) {
if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) {
item = get_next_item(cont, f->rev, &item_first_id);
continue;
}
lv_coord_t grow_size = lv_obj_get_style_flex_grow(item, LV_PART_MAIN);
if(grow_size) {
lv_coord_t s = 0;
for(i = 0; i < t->grow_item_cnt; i++) {
if(t->grow_dsc[i].item == item) {
s = t->grow_dsc[i].final_size;
break;
}
}
if(f->row) {
item->w_layout = 1;
item->h_layout = 0;
}
else {
item->h_layout = 1;
item->w_layout = 0;
}
if(s != area_get_main_size(&item->coords)) {
lv_obj_invalidate(item);
lv_area_t old_coords;
lv_area_copy(&old_coords, &item->coords);
area_set_main_size(&item->coords, s);
lv_event_send(item, LV_EVENT_SIZE_CHANGED, &old_coords);
lv_event_send(lv_obj_get_parent(item), LV_EVENT_CHILD_CHANGED, item);
lv_obj_invalidate(item);
}
}
else {
item->w_layout = 0;
item->h_layout = 0;
}
lv_coord_t cross_pos = 0;
switch(f->cross_place) {
case LV_FLEX_ALIGN_CENTER:
/*Round up the cross size to avoid rounding error when dividing by 2
*The issue comes up e,g, with column direction with center cross direction if an element's width changes*/
cross_pos = (((t->track_cross_size + 1) & (~1)) - area_get_cross_size(&item->coords)) / 2;
break;
case LV_FLEX_ALIGN_END:
cross_pos = t->track_cross_size - area_get_cross_size(&item->coords);
break;
default:
break;
}
if(f->row && rtl) main_pos -= area_get_main_size(&item->coords);
/*Handle percentage value of translate*/
lv_coord_t tr_x = lv_obj_get_style_translate_x(item, LV_PART_MAIN);
lv_coord_t tr_y = lv_obj_get_style_translate_y(item, LV_PART_MAIN);
lv_coord_t w = lv_obj_get_width(item);
lv_coord_t h = lv_obj_get_height(item);
if(LV_COORD_IS_PCT(tr_x)) tr_x = (w * LV_COORD_GET_PCT(tr_x)) / 100;
if(LV_COORD_IS_PCT(tr_y)) tr_y = (h * LV_COORD_GET_PCT(tr_y)) / 100;
lv_coord_t diff_x = abs_x - item->coords.x1 + tr_x;
lv_coord_t diff_y = abs_y - item->coords.y1 + tr_y;
diff_x += f->row ? main_pos : cross_pos;
diff_y += f->row ? cross_pos : main_pos;
if(diff_x || diff_y) {
lv_obj_invalidate(item);
item->coords.x1 += diff_x;
item->coords.x2 += diff_x;
item->coords.y1 += diff_y;
item->coords.y2 += diff_y;
lv_obj_invalidate(item);
lv_obj_move_children_by(item, diff_x, diff_y, false);
}
if(!(f->row && rtl)) main_pos += area_get_main_size(&item->coords) + item_gap + place_gap;
else main_pos -= item_gap + place_gap;
item = get_next_item(cont, f->rev, &item_first_id);
}
}
/**
* Tell a start coordinate and gap for a placement type.
*/
static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt,
lv_coord_t * start_pos, lv_coord_t * gap)
{
if(item_cnt <= 1) {
switch(place) {
case LV_FLEX_ALIGN_SPACE_BETWEEN:
case LV_FLEX_ALIGN_SPACE_AROUND:
case LV_FLEX_ALIGN_SPACE_EVENLY:
place = LV_FLEX_ALIGN_CENTER;
break;
default:
break;
}
}
switch(place) {
case LV_FLEX_ALIGN_CENTER:
*gap = 0;
*start_pos += (max_size - content_size) / 2;
break;
case LV_FLEX_ALIGN_END:
*gap = 0;
*start_pos += max_size - content_size;
break;
case LV_FLEX_ALIGN_SPACE_BETWEEN:
*gap = (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt - 1);
break;
case LV_FLEX_ALIGN_SPACE_AROUND:
*gap += (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt);
*start_pos += *gap / 2;
break;
case LV_FLEX_ALIGN_SPACE_EVENLY:
*gap = (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt + 1);
*start_pos += *gap;
break;
default:
*gap = 0;
}
}
static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id)
{
if(rev) {
(*item_id)--;
if(*item_id >= 0) return cont->spec_attr->children[*item_id];
else return NULL;
}
else {
(*item_id)++;
if((*item_id) < (int32_t)cont->spec_attr->child_cnt) return cont->spec_attr->children[*item_id];
else return NULL;
}
}
#endif /*LV_USE_FLEX*/

View File

@ -0,0 +1,152 @@
/**
* @file lv_flex.h
*
*/
#ifndef LV_FLEX_H
#define LV_FLEX_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../core/lv_obj.h"
#if LV_USE_FLEX
/*********************
* DEFINES
*********************/
#define LV_OBJ_FLAG_FLEX_IN_NEW_TRACK LV_OBJ_FLAG_LAYOUT_1
LV_EXPORT_CONST_INT(LV_OBJ_FLAG_FLEX_IN_NEW_TRACK);
#define _LV_FLEX_COLUMN (1 << 0)
#define _LV_FLEX_WRAP (1 << 2)
#define _LV_FLEX_REVERSE (1 << 3)
/**********************
* TYPEDEFS
**********************/
/*Can't include lv_obj.h because it includes this header file*/
struct _lv_obj_t;
typedef enum {
LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_END,
LV_FLEX_ALIGN_CENTER,
LV_FLEX_ALIGN_SPACE_EVENLY,
LV_FLEX_ALIGN_SPACE_AROUND,
LV_FLEX_ALIGN_SPACE_BETWEEN,
} lv_flex_align_t;
typedef enum {
LV_FLEX_FLOW_ROW = 0x00,
LV_FLEX_FLOW_COLUMN = _LV_FLEX_COLUMN,
LV_FLEX_FLOW_ROW_WRAP = LV_FLEX_FLOW_ROW | _LV_FLEX_WRAP,
LV_FLEX_FLOW_ROW_REVERSE = LV_FLEX_FLOW_ROW | _LV_FLEX_REVERSE,
LV_FLEX_FLOW_ROW_WRAP_REVERSE = LV_FLEX_FLOW_ROW | _LV_FLEX_WRAP | _LV_FLEX_REVERSE,
LV_FLEX_FLOW_COLUMN_WRAP = LV_FLEX_FLOW_COLUMN | _LV_FLEX_WRAP,
LV_FLEX_FLOW_COLUMN_REVERSE = LV_FLEX_FLOW_COLUMN | _LV_FLEX_REVERSE,
LV_FLEX_FLOW_COLUMN_WRAP_REVERSE = LV_FLEX_FLOW_COLUMN | _LV_FLEX_WRAP | _LV_FLEX_REVERSE,
} lv_flex_flow_t;
/**********************
* GLOBAL VARIABLES
**********************/
extern uint16_t LV_LAYOUT_FLEX;
extern lv_style_prop_t LV_STYLE_FLEX_FLOW;
extern lv_style_prop_t LV_STYLE_FLEX_MAIN_PLACE;
extern lv_style_prop_t LV_STYLE_FLEX_CROSS_PLACE;
extern lv_style_prop_t LV_STYLE_FLEX_TRACK_PLACE;
extern lv_style_prop_t LV_STYLE_FLEX_GROW;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize a flex layout the default values
* @param flex pointer to a flex layout descriptor
*/
void lv_flex_init(void);
/**
* Set hot the item should flow
* @param flex pointer to a flex layout descriptor
* @param flow an element of `lv_flex_flow_t`.
*/
void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow);
/**
* Set how to place (where to align) the items and tracks
* @param flex pointer: to a flex layout descriptor
* @param main_place where to place the items on main axis (in their track). Any value of `lv_flex_align_t`.
* @param cross_place where to place the item in their track on the cross axis. `LV_FLEX_ALIGN_START/END/CENTER`
* @param track_place where to place the tracks in the cross direction. Any value of `lv_flex_align_t`.
*/
void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place,
lv_flex_align_t track_cross_place);
/**
* Sets the width or height (on main axis) to grow the object in order fill the free space
* @param obj pointer to an object. The parent must have flex layout else nothing will happen.
* @param grow a value to set how much free space to take proportionally to other growing items.
*/
void lv_obj_set_flex_grow(lv_obj_t * obj, uint8_t grow);
void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value);
void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value);
void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value);
void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value);
void lv_style_set_flex_grow(lv_style_t * style, uint8_t value);
void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector);
void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector);
static inline lv_flex_flow_t lv_obj_get_style_flex_flow(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_FLOW);
return (lv_flex_flow_t)v.num;
}
static inline lv_flex_align_t lv_obj_get_style_flex_main_place(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_MAIN_PLACE);
return (lv_flex_align_t)v.num;
}
static inline lv_flex_align_t lv_obj_get_style_flex_cross_place(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_CROSS_PLACE);
return (lv_flex_align_t)v.num;
}
static inline lv_flex_align_t lv_obj_get_style_flex_track_place(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_TRACK_PLACE);
return (lv_flex_align_t)v.num;
}
static inline uint8_t lv_obj_get_style_flex_grow(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_GROW);
return (uint8_t)v.num;
}
/**********************
* MACROS
**********************/
#endif /*LV_USE_FLEX*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_FLEX_H*/

View File

@ -0,0 +1,782 @@
/**
* @file lv_grid.c
*
*/
/*********************
* INCLUDES
*********************/
#include "../lv_layouts.h"
#if LV_USE_GRID
/*********************
* DEFINES
*********************/
/**
* Some helper defines
*/
#define IS_FR(x) (x >= LV_COORD_MAX - 100)
#define IS_CONTENT(x) (x == LV_COORD_MAX - 101)
#define GET_FR(x) (x - (LV_COORD_MAX - 100))
/**********************
* TYPEDEFS
**********************/
typedef struct {
uint32_t col;
uint32_t row;
lv_point_t grid_abs;
} item_repos_hint_t;
typedef struct {
lv_coord_t * x;
lv_coord_t * y;
lv_coord_t * w;
lv_coord_t * h;
uint32_t col_num;
uint32_t row_num;
lv_coord_t grid_w;
lv_coord_t grid_h;
} _lv_grid_calc_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void grid_update(lv_obj_t * cont, void * user_data);
static void calc(lv_obj_t * obj, _lv_grid_calc_t * calc);
static void calc_free(_lv_grid_calc_t * calc);
static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c);
static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c);
static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * hint);
static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t align, lv_coord_t gap, uint32_t track_num,
lv_coord_t * size_array, lv_coord_t * pos_array, bool reverse);
static uint32_t count_tracks(const lv_coord_t * templ);
static inline const lv_coord_t * get_col_dsc(lv_obj_t * obj)
{
return lv_obj_get_style_grid_column_dsc_array(obj, 0);
}
static inline const lv_coord_t * get_row_dsc(lv_obj_t * obj)
{
return lv_obj_get_style_grid_row_dsc_array(obj, 0);
}
static inline uint8_t get_col_pos(lv_obj_t * obj)
{
return lv_obj_get_style_grid_cell_column_pos(obj, 0);
}
static inline uint8_t get_row_pos(lv_obj_t * obj)
{
return lv_obj_get_style_grid_cell_row_pos(obj, 0);
}
static inline uint8_t get_col_span(lv_obj_t * obj)
{
return lv_obj_get_style_grid_cell_column_span(obj, 0);
}
static inline uint8_t get_row_span(lv_obj_t * obj)
{
return lv_obj_get_style_grid_cell_row_span(obj, 0);
}
static inline uint8_t get_cell_col_align(lv_obj_t * obj)
{
return lv_obj_get_style_grid_cell_x_align(obj, 0);
}
static inline uint8_t get_cell_row_align(lv_obj_t * obj)
{
return lv_obj_get_style_grid_cell_y_align(obj, 0);
}
static inline uint8_t get_grid_col_align(lv_obj_t * obj)
{
return lv_obj_get_style_grid_column_align(obj, 0);
}
static inline uint8_t get_grid_row_align(lv_obj_t * obj)
{
return lv_obj_get_style_grid_row_align(obj, 0);
}
/**********************
* GLOBAL VARIABLES
**********************/
uint16_t LV_LAYOUT_GRID;
lv_style_prop_t LV_STYLE_GRID_COLUMN_DSC_ARRAY;
lv_style_prop_t LV_STYLE_GRID_COLUMN_ALIGN;
lv_style_prop_t LV_STYLE_GRID_ROW_DSC_ARRAY;
lv_style_prop_t LV_STYLE_GRID_ROW_ALIGN;
lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_POS;
lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_SPAN;
lv_style_prop_t LV_STYLE_GRID_CELL_X_ALIGN;
lv_style_prop_t LV_STYLE_GRID_CELL_ROW_POS;
lv_style_prop_t LV_STYLE_GRID_CELL_ROW_SPAN;
lv_style_prop_t LV_STYLE_GRID_CELL_Y_ALIGN;
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_grid_init(void)
{
LV_LAYOUT_GRID = lv_layout_register(grid_update, NULL);
LV_STYLE_GRID_COLUMN_DSC_ARRAY = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
LV_STYLE_GRID_ROW_DSC_ARRAY = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
LV_STYLE_GRID_COLUMN_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
LV_STYLE_GRID_ROW_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
LV_STYLE_GRID_CELL_ROW_SPAN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
LV_STYLE_GRID_CELL_ROW_POS = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
LV_STYLE_GRID_CELL_COLUMN_SPAN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
LV_STYLE_GRID_CELL_COLUMN_POS = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
LV_STYLE_GRID_CELL_X_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
LV_STYLE_GRID_CELL_Y_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
}
void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const lv_coord_t col_dsc[], const lv_coord_t row_dsc[])
{
lv_obj_set_style_grid_column_dsc_array(obj, col_dsc, 0);
lv_obj_set_style_grid_row_dsc_array(obj, row_dsc, 0);
lv_obj_set_style_layout(obj, LV_LAYOUT_GRID, 0);
}
void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid_align_t row_align)
{
lv_obj_set_style_grid_column_align(obj, column_align, 0);
lv_obj_set_style_grid_row_align(obj, row_align, 0);
}
void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t x_align, uint8_t col_pos, uint8_t col_span,
lv_grid_align_t y_align, uint8_t row_pos, uint8_t row_span)
{
lv_obj_set_style_grid_cell_column_pos(obj, col_pos, 0);
lv_obj_set_style_grid_cell_row_pos(obj, row_pos, 0);
lv_obj_set_style_grid_cell_x_align(obj, x_align, 0);
lv_obj_set_style_grid_cell_column_span(obj, col_span, 0);
lv_obj_set_style_grid_cell_row_span(obj, row_span, 0);
lv_obj_set_style_grid_cell_y_align(obj, y_align, 0);
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
}
void lv_style_set_grid_row_dsc_array(lv_style_t * style, const lv_coord_t value[])
{
lv_style_value_t v = {
.ptr = (const void *)value
};
lv_style_set_prop(style, LV_STYLE_GRID_ROW_DSC_ARRAY, v);
}
void lv_style_set_grid_column_dsc_array(lv_style_t * style, const lv_coord_t value[])
{
lv_style_value_t v = {
.ptr = (const void *)value
};
lv_style_set_prop(style, LV_STYLE_GRID_COLUMN_DSC_ARRAY, v);
}
void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value)
{
lv_style_value_t v = {
.num = (lv_grid_align_t)value
};
lv_style_set_prop(style, LV_STYLE_GRID_ROW_ALIGN, v);
}
void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value)
{
lv_style_value_t v = {
.num = (lv_grid_align_t)value
};
lv_style_set_prop(style, LV_STYLE_GRID_COLUMN_ALIGN, v);
}
void lv_style_set_grid_cell_column_pos(lv_style_t * style, lv_coord_t value)
{
lv_style_value_t v = {
.num = value
};
lv_style_set_prop(style, LV_STYLE_GRID_CELL_COLUMN_POS, v);
}
void lv_style_set_grid_cell_column_span(lv_style_t * style, lv_coord_t value)
{
lv_style_value_t v = {
.num = value
};
lv_style_set_prop(style, LV_STYLE_GRID_CELL_COLUMN_SPAN, v);
}
void lv_style_set_grid_cell_row_pos(lv_style_t * style, lv_coord_t value)
{
lv_style_value_t v = {
.num = value
};
lv_style_set_prop(style, LV_STYLE_GRID_CELL_ROW_POS, v);
}
void lv_style_set_grid_cell_row_span(lv_style_t * style, lv_coord_t value)
{
lv_style_value_t v = {
.num = value
};
lv_style_set_prop(style, LV_STYLE_GRID_CELL_ROW_SPAN, v);
}
void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_coord_t value)
{
lv_style_value_t v = {
.num = value
};
lv_style_set_prop(style, LV_STYLE_GRID_CELL_X_ALIGN, v);
}
void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_coord_t value)
{
lv_style_value_t v = {
.num = value
};
lv_style_set_prop(style, LV_STYLE_GRID_CELL_Y_ALIGN, v);
}
void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = (const void *)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_DSC_ARRAY, v, selector);
}
void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = (const void *)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_COLUMN_DSC_ARRAY, v, selector);
}
void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t) value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_ALIGN, v, selector);
}
void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t) value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_COLUMN_ALIGN, v, selector);
}
void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_POS, v, selector);
}
void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_SPAN, v, selector);
}
void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_POS, v, selector);
}
void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_SPAN, v, selector);
}
void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_X_ALIGN, v, selector);
}
void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_Y_ALIGN, v, selector);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void grid_update(lv_obj_t * cont, void * user_data)
{
LV_LOG_INFO("update %p container", (void *)cont);
LV_UNUSED(user_data);
const lv_coord_t * col_templ = get_col_dsc(cont);
const lv_coord_t * row_templ = get_row_dsc(cont);
if(col_templ == NULL || row_templ == NULL) return;
_lv_grid_calc_t c;
calc(cont, &c);
item_repos_hint_t hint;
lv_memset_00(&hint, sizeof(hint));
/*Calculate the grids absolute x and y coordinates.
*It will be used as helper during item repositioning to avoid calculating this value for every children*/
lv_coord_t border_widt = lv_obj_get_style_border_width(cont, LV_PART_MAIN);
lv_coord_t pad_left = lv_obj_get_style_pad_left(cont, LV_PART_MAIN) + border_widt;
lv_coord_t pad_top = lv_obj_get_style_pad_top(cont, LV_PART_MAIN) + border_widt;
hint.grid_abs.x = pad_left + cont->coords.x1 - lv_obj_get_scroll_x(cont);
hint.grid_abs.y = pad_top + cont->coords.y1 - lv_obj_get_scroll_y(cont);
uint32_t i;
for(i = 0; i < cont->spec_attr->child_cnt; i++) {
lv_obj_t * item = cont->spec_attr->children[i];
item_repos(item, &c, &hint);
}
calc_free(&c);
lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN);
lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN);
if(w_set == LV_SIZE_CONTENT || h_set == LV_SIZE_CONTENT) {
lv_obj_refr_size(cont);
}
lv_event_send(cont, LV_EVENT_LAYOUT_CHANGED, NULL);
LV_TRACE_LAYOUT("finished");
}
/**
* Calculate the grid cells coordinates
* @param cont an object that has a grid
* @param calc store the calculated cells sizes here
* @note `_lv_grid_calc_free(calc_out)` needs to be called when `calc_out` is not needed anymore
*/
static void calc(lv_obj_t * cont, _lv_grid_calc_t * calc_out)
{
if(lv_obj_get_child(cont, 0) == NULL) {
lv_memset_00(calc_out, sizeof(_lv_grid_calc_t));
return;
}
calc_rows(cont, calc_out);
calc_cols(cont, calc_out);
lv_coord_t col_gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN);
lv_coord_t row_gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN);
bool rev = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false;
lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN);
lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN);
bool auto_w = (w_set == LV_SIZE_CONTENT && !cont->w_layout) ? true : false;
lv_coord_t cont_w = lv_obj_get_content_width(cont);
calc_out->grid_w = grid_align(cont_w, auto_w, get_grid_col_align(cont), col_gap, calc_out->col_num, calc_out->w,
calc_out->x, rev);
bool auto_h = (h_set == LV_SIZE_CONTENT && !cont->h_layout) ? true : false;
lv_coord_t cont_h = lv_obj_get_content_height(cont);
calc_out->grid_h = grid_align(cont_h, auto_h, get_grid_row_align(cont), row_gap, calc_out->row_num, calc_out->h,
calc_out->y, false);
LV_ASSERT_MEM_INTEGRITY();
}
/**
* Free the a grid calculation's data
* @param calc pointer to the calculated grid cell coordinates
*/
static void calc_free(_lv_grid_calc_t * calc)
{
lv_mem_buf_release(calc->x);
lv_mem_buf_release(calc->y);
lv_mem_buf_release(calc->w);
lv_mem_buf_release(calc->h);
}
static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c)
{
const lv_coord_t * col_templ = get_col_dsc(cont);
lv_coord_t cont_w = lv_obj_get_content_width(cont);
c->col_num = count_tracks(col_templ);
c->x = lv_mem_buf_get(sizeof(lv_coord_t) * c->col_num);
c->w = lv_mem_buf_get(sizeof(lv_coord_t) * c->col_num);
/*Set sizes for CONTENT cells*/
uint32_t i;
for(i = 0; i < c->col_num; i++) {
lv_coord_t size = LV_COORD_MIN;
if(IS_CONTENT(col_templ[i])) {
/*Check the size of children of this cell*/
uint32_t ci;
for(ci = 0; ci < lv_obj_get_child_cnt(cont); ci++) {
lv_obj_t * item = lv_obj_get_child(cont, ci);
if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
uint32_t col_span = get_col_span(item);
if(col_span != 1) continue;
uint32_t col_pos = get_col_pos(item);
if(col_pos != i) continue;
size = LV_MAX(size, lv_obj_get_width(item));
}
if(size >= 0) c->w[i] = size;
else c->w[i] = 0;
}
}
uint32_t col_fr_cnt = 0;
lv_coord_t grid_w = 0;
for(i = 0; i < c->col_num; i++) {
lv_coord_t x = col_templ[i];
if(IS_FR(x)) {
col_fr_cnt += GET_FR(x);
}
else if(IS_CONTENT(x)) {
grid_w += c->w[i];
}
else {
c->w[i] = x;
grid_w += x;
}
}
lv_coord_t col_gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN);
cont_w -= col_gap * (c->col_num - 1);
lv_coord_t free_w = cont_w - grid_w;
if(free_w < 0) free_w = 0;
int32_t last_fr_i = -1;
int32_t last_fr_x = 0;
for(i = 0; i < c->col_num; i++) {
lv_coord_t x = col_templ[i];
if(IS_FR(x)) {
lv_coord_t f = GET_FR(x);
c->w[i] = (free_w * f) / col_fr_cnt;
last_fr_i = i;
last_fr_x = f;
}
}
/*To avoid rounding errors set the last FR track to the remaining size */
if(last_fr_i >= 0) {
c->w[last_fr_i] = free_w - ((free_w * (col_fr_cnt - last_fr_x)) / col_fr_cnt);
}
}
static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c)
{
uint32_t i;
const lv_coord_t * row_templ = get_row_dsc(cont);
c->row_num = count_tracks(row_templ);
c->y = lv_mem_buf_get(sizeof(lv_coord_t) * c->row_num);
c->h = lv_mem_buf_get(sizeof(lv_coord_t) * c->row_num);
/*Set sizes for CONTENT cells*/
for(i = 0; i < c->row_num; i++) {
lv_coord_t size = LV_COORD_MIN;
if(IS_CONTENT(row_templ[i])) {
/*Check the size of children of this cell*/
uint32_t ci;
for(ci = 0; ci < lv_obj_get_child_cnt(cont); ci++) {
lv_obj_t * item = lv_obj_get_child(cont, ci);
if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
uint32_t row_span = get_row_span(item);
if(row_span != 1) continue;
uint32_t row_pos = get_row_pos(item);
if(row_pos != i) continue;
size = LV_MAX(size, lv_obj_get_height(item));
}
if(size >= 0) c->h[i] = size;
else c->h[i] = 0;
}
}
uint32_t row_fr_cnt = 0;
lv_coord_t grid_h = 0;
for(i = 0; i < c->row_num; i++) {
lv_coord_t x = row_templ[i];
if(IS_FR(x)) {
row_fr_cnt += GET_FR(x);
}
else if(IS_CONTENT(x)) {
grid_h += c->h[i];
}
else {
c->h[i] = x;
grid_h += x;
}
}
lv_coord_t row_gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN);
lv_coord_t cont_h = lv_obj_get_content_height(cont) - row_gap * (c->row_num - 1);
lv_coord_t free_h = cont_h - grid_h;
if(free_h < 0) free_h = 0;
int32_t last_fr_i = -1;
int32_t last_fr_x = 0;
for(i = 0; i < c->row_num; i++) {
lv_coord_t x = row_templ[i];
if(IS_FR(x)) {
lv_coord_t f = GET_FR(x);
c->h[i] = (free_h * f) / row_fr_cnt;
last_fr_i = i;
last_fr_x = f;
}
}
/*To avoid rounding errors set the last FR track to the remaining size */
if(last_fr_i >= 0) {
c->h[last_fr_i] = free_h - ((free_h * (row_fr_cnt - last_fr_x)) / row_fr_cnt);
}
}
/**
* Reposition a grid item in its cell
* @param item a grid item to reposition
* @param calc the calculated grid of `cont`
* @param child_id_ext helper value if the ID of the child is know (order from the oldest) else -1
* @param grid_abs helper value, the absolute position of the grid, NULL if unknown
*/
static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * hint)
{
if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) return;
uint32_t col_span = get_col_span(item);
uint32_t row_span = get_row_span(item);
if(row_span == 0 || col_span == 0) return;
uint32_t col_pos = get_col_pos(item);
uint32_t row_pos = get_row_pos(item);
lv_grid_align_t col_align = get_cell_col_align(item);
lv_grid_align_t row_align = get_cell_row_align(item);
lv_coord_t col_x1 = c->x[col_pos];
lv_coord_t col_x2 = c->x[col_pos + col_span - 1] + c->w[col_pos + col_span - 1];
lv_coord_t col_w = col_x2 - col_x1;
lv_coord_t row_y1 = c->y[row_pos];
lv_coord_t row_y2 = c->y[row_pos + row_span - 1] + c->h[row_pos + row_span - 1];
lv_coord_t row_h = row_y2 - row_y1;
/*If the item has RTL base dir switch start and end*/
if(lv_obj_get_style_base_dir(item, LV_PART_MAIN) == LV_BASE_DIR_RTL) {
if(col_align == LV_GRID_ALIGN_START) col_align = LV_GRID_ALIGN_END;
else if(col_align == LV_GRID_ALIGN_END) col_align = LV_GRID_ALIGN_START;
}
lv_coord_t x;
lv_coord_t y;
lv_coord_t item_w = lv_area_get_width(&item->coords);
lv_coord_t item_h = lv_area_get_height(&item->coords);
switch(col_align) {
default:
case LV_GRID_ALIGN_START:
x = c->x[col_pos];
item->w_layout = 0;
break;
case LV_GRID_ALIGN_STRETCH:
x = c->x[col_pos];
item_w = col_w;
item->w_layout = 1;
break;
case LV_GRID_ALIGN_CENTER:
x = c->x[col_pos] + (col_w - item_w) / 2;
item->w_layout = 0;
break;
case LV_GRID_ALIGN_END:
x = c->x[col_pos] + col_w - lv_obj_get_width(item);
item->w_layout = 0;
break;
}
switch(row_align) {
default:
case LV_GRID_ALIGN_START:
y = c->y[row_pos];
item->h_layout = 0;
break;
case LV_GRID_ALIGN_STRETCH:
y = c->y[row_pos];
item_h = row_h;
item->h_layout = 1;
break;
case LV_GRID_ALIGN_CENTER:
y = c->y[row_pos] + (row_h - item_h) / 2;
item->h_layout = 0;
break;
case LV_GRID_ALIGN_END:
y = c->y[row_pos] + row_h - lv_obj_get_height(item);
item->h_layout = 0;
break;
}
/*Set a new size if required*/
if(lv_obj_get_width(item) != item_w || lv_obj_get_height(item) != item_h) {
lv_area_t old_coords;
lv_area_copy(&old_coords, &item->coords);
lv_obj_invalidate(item);
lv_area_set_width(&item->coords, item_w);
lv_area_set_height(&item->coords, item_h);
lv_obj_invalidate(item);
lv_event_send(item, LV_EVENT_SIZE_CHANGED, &old_coords);
lv_event_send(lv_obj_get_parent(item), LV_EVENT_CHILD_CHANGED, item);
}
/*Handle percentage value of translate*/
lv_coord_t tr_x = lv_obj_get_style_translate_x(item, LV_PART_MAIN);
lv_coord_t tr_y = lv_obj_get_style_translate_y(item, LV_PART_MAIN);
lv_coord_t w = lv_obj_get_width(item);
lv_coord_t h = lv_obj_get_height(item);
if(LV_COORD_IS_PCT(tr_x)) tr_x = (w * LV_COORD_GET_PCT(tr_x)) / 100;
if(LV_COORD_IS_PCT(tr_y)) tr_y = (h * LV_COORD_GET_PCT(tr_y)) / 100;
x += tr_x;
y += tr_y;
lv_coord_t diff_x = hint->grid_abs.x + x - item->coords.x1;
lv_coord_t diff_y = hint->grid_abs.y + y - item->coords.y1;
if(diff_x || diff_y) {
lv_obj_invalidate(item);
item->coords.x1 += diff_x;
item->coords.x2 += diff_x;
item->coords.y1 += diff_y;
item->coords.y2 += diff_y;
lv_obj_invalidate(item);
lv_obj_move_children_by(item, diff_x, diff_y, false);
}
}
/**
* Place the grid track according to align methods. It keeps the track sizes but sets their position.
* It can process both columns or rows according to the passed parameters.
* @param cont_size size of the containers content area (width/height)
* @param auto_size true: the container has auto size in the current direction
* @param align align method
* @param gap grid gap
* @param track_num number of tracks
* @param size_array array with the track sizes
* @param pos_array write the positions of the tracks here
* @return the total size of the grid
*/
static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t align, lv_coord_t gap, uint32_t track_num,
lv_coord_t * size_array, lv_coord_t * pos_array, bool reverse)
{
lv_coord_t grid_size = 0;
uint32_t i;
if(auto_size) {
pos_array[0] = 0;
}
else {
/*With spaced alignment gap will be calculated from the remaining space*/
if(align == LV_GRID_ALIGN_SPACE_AROUND || align == LV_GRID_ALIGN_SPACE_BETWEEN || align == LV_GRID_ALIGN_SPACE_EVENLY) {
gap = 0;
if(track_num == 1) align = LV_GRID_ALIGN_CENTER;
}
/*Get the full grid size with gap*/
for(i = 0; i < track_num; i++) {
grid_size += size_array[i] + gap;
}
grid_size -= gap;
/*Calculate the position of the first item and set gap is necessary*/
switch(align) {
case LV_GRID_ALIGN_START:
pos_array[0] = 0;
break;
case LV_GRID_ALIGN_CENTER:
pos_array[0] = (cont_size - grid_size) / 2;
break;
case LV_GRID_ALIGN_END:
pos_array[0] = cont_size - grid_size;
break;
case LV_GRID_ALIGN_SPACE_BETWEEN:
pos_array[0] = 0;
gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num - 1);
break;
case LV_GRID_ALIGN_SPACE_AROUND:
gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num);
pos_array[0] = gap / 2;
break;
case LV_GRID_ALIGN_SPACE_EVENLY:
gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num + 1);
pos_array[0] = gap;
break;
}
}
/*Set the position of all tracks from the start position, gaps and track sizes*/
for(i = 0; i < track_num - 1; i++) {
pos_array[i + 1] = pos_array[i] + size_array[i] + gap;
}
lv_coord_t total_gird_size = pos_array[track_num - 1] + size_array[track_num - 1] - pos_array[0];
if(reverse) {
for(i = 0; i < track_num; i++) {
pos_array[i] = cont_size - pos_array[i] - size_array[i];
}
}
/*Return the full size of the grid*/
return total_gird_size;
}
static uint32_t count_tracks(const lv_coord_t * templ)
{
uint32_t i;
for(i = 0; templ[i] != LV_GRID_TEMPLATE_LAST; i++);
return i;
}
#endif /*LV_USE_GRID*/

View File

@ -0,0 +1,194 @@
/**
* @file lv_grid.h
*
*/
#ifndef LV_GRID_H
#define LV_GRID_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../core/lv_obj.h"
#if LV_USE_GRID
/*********************
* DEFINES
*********************/
/**
* Can be used track size to make the track fill the free space.
* @param x how much space to take proportionally to other FR tracks
* @return a special track size
*/
#define LV_GRID_FR(x) (LV_COORD_MAX - 100 + x)
#define LV_GRID_CONTENT (LV_COORD_MAX - 101)
LV_EXPORT_CONST_INT(LV_GRID_CONTENT);
#define LV_GRID_TEMPLATE_LAST (LV_COORD_MAX)
LV_EXPORT_CONST_INT(LV_GRID_TEMPLATE_LAST);
/**********************
* TYPEDEFS
**********************/
/*Can't include lv_obj.h because it includes this header file*/
struct _lv_obj_t;
typedef enum {
LV_GRID_ALIGN_START,
LV_GRID_ALIGN_CENTER,
LV_GRID_ALIGN_END,
LV_GRID_ALIGN_STRETCH,
LV_GRID_ALIGN_SPACE_EVENLY,
LV_GRID_ALIGN_SPACE_AROUND,
LV_GRID_ALIGN_SPACE_BETWEEN,
} lv_grid_align_t;
/**********************
* GLOBAL VARIABLES
**********************/
extern uint16_t LV_LAYOUT_GRID;
extern lv_style_prop_t LV_STYLE_GRID_COLUMN_DSC_ARRAY;
extern lv_style_prop_t LV_STYLE_GRID_COLUMN_ALIGN;
extern lv_style_prop_t LV_STYLE_GRID_ROW_DSC_ARRAY;
extern lv_style_prop_t LV_STYLE_GRID_ROW_ALIGN;
extern lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_POS;
extern lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_SPAN;
extern lv_style_prop_t LV_STYLE_GRID_CELL_X_ALIGN;
extern lv_style_prop_t LV_STYLE_GRID_CELL_ROW_POS;
extern lv_style_prop_t LV_STYLE_GRID_CELL_ROW_SPAN;
extern lv_style_prop_t LV_STYLE_GRID_CELL_Y_ALIGN;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_grid_init(void);
void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const lv_coord_t col_dsc[], const lv_coord_t row_dsc[]);
void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid_align_t row_align);
/**
* Set the cell of an object. The object's parent needs to have grid layout, else nothing will happen
* @param obj pointer to an object
* @param column_align the vertical alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH`
* @param col_pos column ID
* @param col_span number of columns to take (>= 1)
* @param row_align the horizontal alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH`
* @param row_pos row ID
* @param row_span number of rows to take (>= 1)
*/
void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t column_align, uint8_t col_pos, uint8_t col_span,
lv_grid_align_t row_align, uint8_t row_pos, uint8_t row_span);
/**
* Just a wrapper to `LV_GRID_FR` for bindings.
*/
static inline lv_coord_t lv_grid_fr(uint8_t x)
{
return LV_GRID_FR(x);
}
void lv_style_set_grid_row_dsc_array(lv_style_t * style, const lv_coord_t value[]);
void lv_style_set_grid_column_dsc_array(lv_style_t * style, const lv_coord_t value[]);
void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value);
void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value);
void lv_style_set_grid_cell_column_pos(lv_style_t * style, lv_coord_t value);
void lv_style_set_grid_cell_column_span(lv_style_t * style, lv_coord_t value);
void lv_style_set_grid_cell_row_pos(lv_style_t * style, lv_coord_t value);
void lv_style_set_grid_cell_row_span(lv_style_t * style, lv_coord_t value);
void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_coord_t value);
void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_coord_t value);
void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector);
void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector);
void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
static inline const lv_coord_t * lv_obj_get_style_grid_row_dsc_array(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_ROW_DSC_ARRAY);
return (const lv_coord_t *)v.ptr;
}
static inline const lv_coord_t * lv_obj_get_style_grid_column_dsc_array(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_COLUMN_DSC_ARRAY);
return (const lv_coord_t *)v.ptr;
}
static inline lv_grid_align_t lv_obj_get_style_grid_row_align(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_ROW_ALIGN);
return (lv_grid_align_t)v.num;
}
static inline lv_grid_align_t lv_obj_get_style_grid_column_align(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_COLUMN_ALIGN);
return (lv_grid_align_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_grid_cell_column_pos(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_COLUMN_POS);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_grid_cell_column_span(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_COLUMN_SPAN);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_grid_cell_row_pos(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_ROW_POS);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_grid_cell_row_span(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_ROW_SPAN);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_grid_cell_x_align(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_X_ALIGN);
return (lv_coord_t)v.num;
}
static inline lv_coord_t lv_obj_get_style_grid_cell_y_align(const lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_Y_ALIGN);
return (lv_coord_t)v.num;
}
/**********************
* GLOBAL VARIABLES
**********************/
/**********************
* MACROS
**********************/
#endif /*LV_USE_GRID*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_GRID_H*/

View File

@ -0,0 +1,44 @@
/**
* @file lv_layouts.h
*
*/
#ifndef LV_LAYOUTS_H
#define LV_LAYOUTS_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "flex/lv_flex.h"
#include "grid/lv_grid.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#if LV_USE_LOG && LV_LOG_TRACE_LAYOUT
# define LV_TRACE_LAYOUT(...) LV_LOG_TRACE(__VA_ARGS__)
#else
# define LV_TRACE_LAYOUT(...)
#endif
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_LAYOUTS_H*/

View File

@ -0,0 +1,258 @@
/**
* @file lv_bmp.c
*
*/
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_BMP
#include <string.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_fs_file_t f;
unsigned int px_offset;
int px_width;
int px_height;
unsigned int bpp;
int row_size_bytes;
} bmp_dsc_t;
/**********************
* STATIC PROTOTYPES
**********************/
static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header);
static lv_res_t decoder_open(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc);
static lv_res_t decoder_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc,
lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf);
static void decoder_close(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_bmp_init(void)
{
lv_img_decoder_t * dec = lv_img_decoder_create();
lv_img_decoder_set_info_cb(dec, decoder_info);
lv_img_decoder_set_open_cb(dec, decoder_open);
lv_img_decoder_set_read_line_cb(dec, decoder_read_line);
lv_img_decoder_set_close_cb(dec, decoder_close);
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Get info about a PNG image
* @param src can be file name or pointer to a C array
* @param header store the info here
* @return LV_RES_OK: no error; LV_RES_INV: can't get the info
*/
static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header)
{
LV_UNUSED(decoder);
lv_img_src_t src_type = lv_img_src_get_type(src); /*Get the source type*/
/*If it's a BMP file...*/
if(src_type == LV_IMG_SRC_FILE) {
const char * fn = src;
if(strcmp(lv_fs_get_ext(fn), "bmp") == 0) { /*Check the extension*/
/*Save the data in the header*/
lv_fs_file_t f;
lv_fs_res_t res = lv_fs_open(&f, src, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) return LV_RES_INV;
uint8_t headers[54];
lv_fs_read(&f, headers, 54, NULL);
uint32_t w;
uint32_t h;
memcpy(&w, headers + 18, 4);
memcpy(&h, headers + 22, 4);
header->w = w;
header->h = h;
header->always_zero = 0;
lv_fs_close(&f);
#if LV_COLOR_DEPTH == 32
uint16_t bpp;
memcpy(&bpp, headers + 28, 2);
header->cf = bpp == 32 ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR;
#else
header->cf = LV_IMG_CF_TRUE_COLOR;
#endif
return LV_RES_OK;
}
}
/* BMP file as data not supported for simplicity.
* Convert them to LVGL compatible C arrays directly. */
else if(src_type == LV_IMG_SRC_VARIABLE) {
return LV_RES_INV;
}
return LV_RES_INV; /*If didn't succeeded earlier then it's an error*/
}
/**
* Open a PNG image and return the decided image
* @param src can be file name or pointer to a C array
* @param style style of the image object (unused now but certain formats might use it)
* @return pointer to the decoded image or `LV_IMG_DECODER_OPEN_FAIL` if failed
*/
static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
{
LV_UNUSED(decoder);
/*If it's a PNG file...*/
if(dsc->src_type == LV_IMG_SRC_FILE) {
const char * fn = dsc->src;
if(strcmp(lv_fs_get_ext(fn), "bmp") != 0) {
return LV_RES_INV; /*Check the extension*/
}
bmp_dsc_t b;
memset(&b, 0x00, sizeof(b));
lv_fs_res_t res = lv_fs_open(&b.f, dsc->src, LV_FS_MODE_RD);
if(res == LV_RES_OK) return LV_RES_INV;
uint8_t header[54];
lv_fs_read(&b.f, header, 54, NULL);
if(0x42 != header[0] || 0x4d != header[1]) {
lv_fs_close(&b.f);
return LV_RES_INV;
}
memcpy(&b.px_offset, header + 10, 4);
memcpy(&b.px_width, header + 18, 4);
memcpy(&b.px_height, header + 22, 4);
memcpy(&b.bpp, header + 28, 2);
b.row_size_bytes = ((b.bpp * b.px_width + 31) / 32) * 4;
bool color_depth_error = false;
if(LV_COLOR_DEPTH == 32 && (b.bpp != 32 && b.bpp != 24)) {
LV_LOG_WARN("LV_COLOR_DEPTH == 32 but bpp is %d (should be 32 or 24)", b.bpp);
color_depth_error = true;
}
else if(LV_COLOR_DEPTH == 16 && b.bpp != 16) {
LV_LOG_WARN("LV_COLOR_DEPTH == 16 but bpp is %d (should be 16)", b.bpp);
color_depth_error = true;
}
else if(LV_COLOR_DEPTH == 8 && b.bpp != 8) {
LV_LOG_WARN("LV_COLOR_DEPTH == 8 but bpp is %d (should be 8)", b.bpp);
color_depth_error = true;
}
if(color_depth_error) {
dsc->error_msg = "Color depth mismatch";
lv_fs_close(&b.f);
return LV_RES_INV;
}
dsc->user_data = lv_mem_alloc(sizeof(bmp_dsc_t));
LV_ASSERT_MALLOC(dsc->user_data);
if(dsc->user_data == NULL) return LV_RES_INV;
memcpy(dsc->user_data, &b, sizeof(b));
dsc->img_data = NULL;
return LV_RES_OK;
}
/* BMP file as data not supported for simplicity.
* Convert them to LVGL compatible C arrays directly. */
else if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
return LV_RES_INV;
}
return LV_RES_INV; /*If not returned earlier then it failed*/
}
static lv_res_t decoder_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc,
lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf)
{
LV_UNUSED(decoder);
bmp_dsc_t * b = dsc->user_data;
y = (b->px_height - 1) - y; /*BMP images are stored upside down*/
uint32_t p = b->px_offset + b->row_size_bytes * y;
p += x * (b->bpp / 8);
lv_fs_seek(&b->f, p, LV_FS_SEEK_SET);
lv_fs_read(&b->f, buf, len * (b->bpp / 8), NULL);
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 1
for(unsigned int i = 0; i < len * (b->bpp / 8); i += 2) {
buf[i] = buf[i] ^ buf[i + 1];
buf[i + 1] = buf[i] ^ buf[i + 1];
buf[i] = buf[i] ^ buf[i + 1];
}
#elif LV_COLOR_DEPTH == 32
if(b->bpp == 32) {
lv_coord_t i;
for(i = 0; i < len; i++) {
uint8_t b0 = buf[i * 4];
uint8_t b1 = buf[i * 4 + 1];
uint8_t b2 = buf[i * 4 + 2];
uint8_t b3 = buf[i * 4 + 3];
lv_color32_t * c = (lv_color32_t *)&buf[i * 4];
c->ch.red = b2;
c->ch.green = b1;
c->ch.blue = b0;
c->ch.alpha = b3;
}
}
if(b->bpp == 24) {
lv_coord_t i;
for(i = len - 1; i >= 0; i--) {
uint8_t * t = &buf[i * 3];
lv_color32_t * c = (lv_color32_t *)&buf[i * 4];
c->ch.red = t[2];
c->ch.green = t[1];
c->ch.blue = t[0];
c->ch.alpha = 0xff;
}
}
#endif
return LV_RES_OK;
}
/**
* Free the allocated resources
*/
static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
{
LV_UNUSED(decoder);
bmp_dsc_t * b = dsc->user_data;
lv_fs_close(&b->f);
lv_mem_free(dsc->user_data);
}
#endif /*LV_USE_BMP*/

View File

@ -0,0 +1,42 @@
/**
* @file lv_bmp.h
*
*/
#ifndef LV_BMP_H
#define LV_BMP_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_BMP
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_bmp_init(void);
/**********************
* MACROS
**********************/
#endif /*LV_USE_BMP*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_BMP_H*/

View File

@ -0,0 +1,875 @@
/**
* @file lv_ffmpeg.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_ffmpeg.h"
#if LV_USE_FFMPEG != 0
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libswscale/swscale.h>
/*********************
* DEFINES
*********************/
#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8
#define AV_PIX_FMT_TRUE_COLOR AV_PIX_FMT_RGB8
#elif LV_COLOR_DEPTH == 16
#if LV_COLOR_16_SWAP == 0
#define AV_PIX_FMT_TRUE_COLOR AV_PIX_FMT_RGB565LE
#else
#define AV_PIX_FMT_TRUE_COLOR AV_PIX_FMT_RGB565BE
#endif
#elif LV_COLOR_DEPTH == 32
#define AV_PIX_FMT_TRUE_COLOR AV_PIX_FMT_BGR0
#else
#error Unsupported LV_COLOR_DEPTH
#endif
#define MY_CLASS &lv_ffmpeg_player_class
#define FRAME_DEF_REFR_PERIOD 33 /*[ms]*/
/**********************
* TYPEDEFS
**********************/
struct ffmpeg_context_s {
AVFormatContext * fmt_ctx;
AVCodecContext * video_dec_ctx;
AVStream * video_stream;
uint8_t * video_src_data[4];
uint8_t * video_dst_data[4];
struct SwsContext * sws_ctx;
AVFrame * frame;
AVPacket pkt;
int video_stream_idx;
int video_src_linesize[4];
int video_dst_linesize[4];
enum AVPixelFormat video_dst_pix_fmt;
bool has_alpha;
};
#pragma pack(1)
struct lv_img_pixel_color_s {
lv_color_t c;
uint8_t alpha;
};
#pragma pack()
/**********************
* STATIC PROTOTYPES
**********************/
static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header);
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 struct ffmpeg_context_s * ffmpeg_open_file(const char * path);
static void ffmpeg_close(struct ffmpeg_context_s * ffmpeg_ctx);
static void ffmpeg_close_src_ctx(struct ffmpeg_context_s * ffmpeg_ctx);
static void ffmpeg_close_dst_ctx(struct ffmpeg_context_s * ffmpeg_ctx);
static int ffmpeg_image_allocate(struct ffmpeg_context_s * ffmpeg_ctx);
static int ffmpeg_get_img_header(const char * path, lv_img_header_t * header);
static int ffmpeg_get_frame_refr_period(struct ffmpeg_context_s * ffmpeg_ctx);
static uint8_t * ffmpeg_get_img_data(struct ffmpeg_context_s * ffmpeg_ctx);
static int ffmpeg_update_next_frame(struct ffmpeg_context_s * ffmpeg_ctx);
static int ffmpeg_output_video_frame(struct ffmpeg_context_s * ffmpeg_ctx);
static bool ffmpeg_pix_fmt_has_alpha(enum AVPixelFormat pix_fmt);
static bool ffmpeg_pix_fmt_is_yuv(enum AVPixelFormat pix_fmt);
static void lv_ffmpeg_player_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
static void lv_ffmpeg_player_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
#if LV_COLOR_DEPTH != 32
static void convert_color_depth(uint8_t * img, uint32_t px_cnt);
#endif
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_ffmpeg_player_class = {
.constructor_cb = lv_ffmpeg_player_constructor,
.destructor_cb = lv_ffmpeg_player_destructor,
.instance_size = sizeof(lv_ffmpeg_player_t),
.base_class = &lv_img_class
};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_ffmpeg_init(void)
{
lv_img_decoder_t * dec = lv_img_decoder_create();
lv_img_decoder_set_info_cb(dec, decoder_info);
lv_img_decoder_set_open_cb(dec, decoder_open);
lv_img_decoder_set_close_cb(dec, decoder_close);
#if LV_FFMPEG_AV_DUMP_FORMAT == 0
av_log_set_level(AV_LOG_QUIET);
#endif
}
int lv_ffmpeg_get_frame_num(const char * path)
{
int ret = -1;
struct ffmpeg_context_s * ffmpeg_ctx = ffmpeg_open_file(path);
if(ffmpeg_ctx) {
ret = ffmpeg_ctx->video_stream->nb_frames;
ffmpeg_close(ffmpeg_ctx);
}
return ret;
}
lv_obj_t * lv_ffmpeg_player_create(lv_obj_t * parent)
{
lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
lv_obj_class_init_obj(obj);
return obj;
}
lv_res_t lv_ffmpeg_player_set_src(lv_obj_t * obj, const char * path)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_res_t res = LV_RES_INV;
lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj;
if(player->ffmpeg_ctx) {
ffmpeg_close(player->ffmpeg_ctx);
player->ffmpeg_ctx = NULL;
}
lv_timer_pause(player->timer);
player->ffmpeg_ctx = ffmpeg_open_file(path);
if(!player->ffmpeg_ctx) {
LV_LOG_ERROR("ffmpeg file open failed: %s", path);
goto failed;
}
if(ffmpeg_image_allocate(player->ffmpeg_ctx) < 0) {
LV_LOG_ERROR("ffmpeg image allocate failed");
ffmpeg_close(player->ffmpeg_ctx);
goto failed;
}
bool has_alpha = player->ffmpeg_ctx->has_alpha;
int width = player->ffmpeg_ctx->video_dec_ctx->width;
int height = player->ffmpeg_ctx->video_dec_ctx->height;
uint32_t data_size = 0;
if(has_alpha) {
data_size = width * height * LV_IMG_PX_SIZE_ALPHA_BYTE;
}
else {
data_size = width * height * LV_COLOR_SIZE / 8;
}
player->imgdsc.header.always_zero = 0;
player->imgdsc.header.w = width;
player->imgdsc.header.h = height;
player->imgdsc.data_size = data_size;
player->imgdsc.header.cf = has_alpha ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR;
player->imgdsc.data = ffmpeg_get_img_data(player->ffmpeg_ctx);
lv_img_set_src(&player->img.obj, &(player->imgdsc));
int period = ffmpeg_get_frame_refr_period(player->ffmpeg_ctx);
if(period > 0) {
LV_LOG_INFO("frame refresh period = %d ms, rate = %d fps",
period, 1000 / period);
lv_timer_set_period(player->timer, period);
}
else {
LV_LOG_WARN("unable to get frame refresh period");
}
res = LV_RES_OK;
failed:
return res;
}
void lv_ffmpeg_player_set_cmd(lv_obj_t * obj, lv_ffmpeg_player_cmd_t cmd)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj;
if(!player->ffmpeg_ctx) {
LV_LOG_ERROR("ffmpeg_ctx is NULL");
return;
}
lv_timer_t * timer = player->timer;
switch(cmd) {
case LV_FFMPEG_PLAYER_CMD_START:
av_seek_frame(player->ffmpeg_ctx->fmt_ctx,
0, 0, AVSEEK_FLAG_BACKWARD);
lv_timer_resume(timer);
LV_LOG_INFO("ffmpeg player start");
break;
case LV_FFMPEG_PLAYER_CMD_STOP:
av_seek_frame(player->ffmpeg_ctx->fmt_ctx,
0, 0, AVSEEK_FLAG_BACKWARD);
lv_timer_pause(timer);
LV_LOG_INFO("ffmpeg player stop");
break;
case LV_FFMPEG_PLAYER_CMD_PAUSE:
lv_timer_pause(timer);
LV_LOG_INFO("ffmpeg player pause");
break;
case LV_FFMPEG_PLAYER_CMD_RESUME:
lv_timer_resume(timer);
LV_LOG_INFO("ffmpeg player resume");
break;
default:
LV_LOG_ERROR("Error cmd: %d", cmd);
break;
}
}
void lv_ffmpeg_player_set_auto_restart(lv_obj_t * obj, bool en)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj;
player->auto_restart = en;
}
/**********************
* STATIC FUNCTIONS
**********************/
static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header)
{
/* Get the source type */
lv_img_src_t src_type = lv_img_src_get_type(src);
if(src_type == LV_IMG_SRC_FILE) {
const char * fn = src;
if(ffmpeg_get_img_header(fn, header) < 0) {
LV_LOG_ERROR("ffmpeg can't get image header");
return LV_RES_INV;
}
return LV_RES_OK;
}
/* If didn't succeeded earlier then it's an error */
return LV_RES_INV;
}
static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
{
if(dsc->src_type == LV_IMG_SRC_FILE) {
const char * path = dsc->src;
struct ffmpeg_context_s * ffmpeg_ctx = ffmpeg_open_file(path);
if(ffmpeg_ctx == NULL) {
return LV_RES_INV;
}
if(ffmpeg_image_allocate(ffmpeg_ctx) < 0) {
LV_LOG_ERROR("ffmpeg image allocate failed");
ffmpeg_close(ffmpeg_ctx);
return LV_RES_INV;
}
if(ffmpeg_update_next_frame(ffmpeg_ctx) < 0) {
ffmpeg_close(ffmpeg_ctx);
LV_LOG_ERROR("ffmpeg update frame failed");
return LV_RES_INV;
}
ffmpeg_close_src_ctx(ffmpeg_ctx);
uint8_t * img_data = ffmpeg_get_img_data(ffmpeg_ctx);
#if LV_COLOR_DEPTH != 32
if(ffmpeg_ctx->has_alpha) {
convert_color_depth(img_data, dsc->header.w * dsc->header.h);
}
#endif
dsc->user_data = ffmpeg_ctx;
dsc->img_data = img_data;
/* The image is fully decoded. Return with its pointer */
return LV_RES_OK;
}
/* If not returned earlier then it failed */
return LV_RES_INV;
}
static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
{
struct ffmpeg_context_s * ffmpeg_ctx = dsc->user_data;
ffmpeg_close(ffmpeg_ctx);
}
#if LV_COLOR_DEPTH != 32
static void convert_color_depth(uint8_t * img, uint32_t px_cnt)
{
lv_color32_t * img_src_p = (lv_color32_t *)img;
struct lv_img_pixel_color_s * img_dst_p = (struct lv_img_pixel_color_s *)img;
for(uint32_t i = 0; i < px_cnt; i++) {
lv_color32_t temp = *img_src_p;
img_dst_p->c = lv_color_hex(temp.full);
img_dst_p->alpha = temp.ch.alpha;
img_src_p++;
img_dst_p++;
}
}
#endif
static uint8_t * ffmpeg_get_img_data(struct ffmpeg_context_s * ffmpeg_ctx)
{
uint8_t * img_data = ffmpeg_ctx->video_dst_data[0];
if(img_data == NULL) {
LV_LOG_ERROR("ffmpeg video dst data is NULL");
}
return img_data;
}
static bool ffmpeg_pix_fmt_has_alpha(enum AVPixelFormat pix_fmt)
{
const AVPixFmtDescriptor * desc = av_pix_fmt_desc_get(pix_fmt);
if(desc == NULL) {
return false;
}
if(pix_fmt == AV_PIX_FMT_PAL8) {
return true;
}
return (desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? true : false;
}
static bool ffmpeg_pix_fmt_is_yuv(enum AVPixelFormat pix_fmt)
{
const AVPixFmtDescriptor * desc = av_pix_fmt_desc_get(pix_fmt);
if(desc == NULL) {
return false;
}
return !(desc->flags & AV_PIX_FMT_FLAG_RGB) && desc->nb_components >= 2;
}
static int ffmpeg_output_video_frame(struct ffmpeg_context_s * ffmpeg_ctx)
{
int ret = -1;
int width = ffmpeg_ctx->video_dec_ctx->width;
int height = ffmpeg_ctx->video_dec_ctx->height;
AVFrame * frame = ffmpeg_ctx->frame;
if(frame->width != width
|| frame->height != height
|| frame->format != ffmpeg_ctx->video_dec_ctx->pix_fmt) {
/* To handle this change, one could call av_image_alloc again and
* decode the following frames into another rawvideo file.
*/
LV_LOG_ERROR("Width, height and pixel format have to be "
"constant in a rawvideo file, but the width, height or "
"pixel format of the input video changed:\n"
"old: width = %d, height = %d, format = %s\n"
"new: width = %d, height = %d, format = %s\n",
width,
height,
av_get_pix_fmt_name(ffmpeg_ctx->video_dec_ctx->pix_fmt),
frame->width, frame->height,
av_get_pix_fmt_name(frame->format));
goto failed;
}
LV_LOG_TRACE("video_frame coded_n:%d", frame->coded_picture_number);
/* copy decoded frame to destination buffer:
* this is required since rawvideo expects non aligned data
*/
av_image_copy(ffmpeg_ctx->video_src_data, ffmpeg_ctx->video_src_linesize,
(const uint8_t **)(frame->data), frame->linesize,
ffmpeg_ctx->video_dec_ctx->pix_fmt, width, height);
if(ffmpeg_ctx->sws_ctx == NULL) {
int swsFlags = SWS_BILINEAR;
if(ffmpeg_pix_fmt_is_yuv(ffmpeg_ctx->video_dec_ctx->pix_fmt)) {
/* When the video width and height are not multiples of 8,
* and there is no size change in the conversion,
* a blurry screen will appear on the right side
* This problem was discovered in 2012 and
* continues to exist in version 4.1.3 in 2019
* This problem can be avoided by increasing SWS_ACCURATE_RND
*/
if((width & 0x7) || (height & 0x7)) {
LV_LOG_WARN("The width(%d) and height(%d) the image "
"is not a multiple of 8, "
"the decoding speed may be reduced",
width, height);
swsFlags |= SWS_ACCURATE_RND;
}
}
ffmpeg_ctx->sws_ctx = sws_getContext(
width, height, ffmpeg_ctx->video_dec_ctx->pix_fmt,
width, height, ffmpeg_ctx->video_dst_pix_fmt,
swsFlags,
NULL, NULL, NULL);
}
if(!ffmpeg_ctx->has_alpha) {
int lv_linesize = sizeof(lv_color_t) * width;
int dst_linesize = ffmpeg_ctx->video_dst_linesize[0];
if(dst_linesize != lv_linesize) {
LV_LOG_WARN("ffmpeg linesize = %d, but lvgl image require %d",
dst_linesize,
lv_linesize);
ffmpeg_ctx->video_dst_linesize[0] = lv_linesize;
}
}
ret = sws_scale(
ffmpeg_ctx->sws_ctx,
(const uint8_t * const *)(ffmpeg_ctx->video_src_data),
ffmpeg_ctx->video_src_linesize,
0,
height,
ffmpeg_ctx->video_dst_data,
ffmpeg_ctx->video_dst_linesize);
failed:
return ret;
}
static int ffmpeg_decode_packet(AVCodecContext * dec, const AVPacket * pkt,
struct ffmpeg_context_s * ffmpeg_ctx)
{
int ret = 0;
/* submit the packet to the decoder */
ret = avcodec_send_packet(dec, pkt);
if(ret < 0) {
LV_LOG_ERROR("Error submitting a packet for decoding (%s)",
av_err2str(ret));
return ret;
}
/* get all the available frames from the decoder */
while(ret >= 0) {
ret = avcodec_receive_frame(dec, ffmpeg_ctx->frame);
if(ret < 0) {
/* those two return values are special and mean there is
* no output frame available,
* but there were no errors during decoding
*/
if(ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) {
return 0;
}
LV_LOG_ERROR("Error during decoding (%s)", av_err2str(ret));
return ret;
}
/* write the frame data to output file */
if(dec->codec->type == AVMEDIA_TYPE_VIDEO) {
ret = ffmpeg_output_video_frame(ffmpeg_ctx);
}
av_frame_unref(ffmpeg_ctx->frame);
if(ret < 0) {
LV_LOG_WARN("ffmpeg_decode_packet ended %d", ret);
return ret;
}
}
return 0;
}
static int ffmpeg_open_codec_context(int * stream_idx,
AVCodecContext ** dec_ctx, AVFormatContext * fmt_ctx,
enum AVMediaType type)
{
int ret;
int stream_index;
AVStream * st;
AVCodec * dec = NULL;
AVDictionary * opts = NULL;
ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
if(ret < 0) {
LV_LOG_ERROR("Could not find %s stream in input file",
av_get_media_type_string(type));
return ret;
}
else {
stream_index = ret;
st = fmt_ctx->streams[stream_index];
/* find decoder for the stream */
dec = avcodec_find_decoder(st->codecpar->codec_id);
if(dec == NULL) {
LV_LOG_ERROR("Failed to find %s codec",
av_get_media_type_string(type));
return AVERROR(EINVAL);
}
/* Allocate a codec context for the decoder */
*dec_ctx = avcodec_alloc_context3(dec);
if(*dec_ctx == NULL) {
LV_LOG_ERROR("Failed to allocate the %s codec context",
av_get_media_type_string(type));
return AVERROR(ENOMEM);
}
/* Copy codec parameters from input stream to output codec context */
if((ret = avcodec_parameters_to_context(*dec_ctx, st->codecpar)) < 0) {
LV_LOG_ERROR(
"Failed to copy %s codec parameters to decoder context",
av_get_media_type_string(type));
return ret;
}
/* Init the decoders */
if((ret = avcodec_open2(*dec_ctx, dec, &opts)) < 0) {
LV_LOG_ERROR("Failed to open %s codec",
av_get_media_type_string(type));
return ret;
}
*stream_idx = stream_index;
}
return 0;
}
static int ffmpeg_get_img_header(const char * filepath,
lv_img_header_t * header)
{
int ret = -1;
AVFormatContext * fmt_ctx = NULL;
AVCodecContext * video_dec_ctx = NULL;
int video_stream_idx;
/* open input file, and allocate format context */
if(avformat_open_input(&fmt_ctx, filepath, NULL, NULL) < 0) {
LV_LOG_ERROR("Could not open source file %s", filepath);
goto failed;
}
/* retrieve stream information */
if(avformat_find_stream_info(fmt_ctx, NULL) < 0) {
LV_LOG_ERROR("Could not find stream information");
goto failed;
}
if(ffmpeg_open_codec_context(&video_stream_idx, &video_dec_ctx,
fmt_ctx, AVMEDIA_TYPE_VIDEO)
>= 0) {
bool has_alpha = ffmpeg_pix_fmt_has_alpha(video_dec_ctx->pix_fmt);
/* allocate image where the decoded image will be put */
header->w = video_dec_ctx->width;
header->h = video_dec_ctx->height;
header->always_zero = 0;
header->cf = (has_alpha ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR);
ret = 0;
}
failed:
avcodec_free_context(&video_dec_ctx);
avformat_close_input(&fmt_ctx);
return ret;
}
static int ffmpeg_get_frame_refr_period(struct ffmpeg_context_s * ffmpeg_ctx)
{
int avg_frame_rate_num = ffmpeg_ctx->video_stream->avg_frame_rate.num;
if(avg_frame_rate_num > 0) {
int period = 1000 * (int64_t)ffmpeg_ctx->video_stream->avg_frame_rate.den
/ avg_frame_rate_num;
return period;
}
return -1;
}
static int ffmpeg_update_next_frame(struct ffmpeg_context_s * ffmpeg_ctx)
{
int ret = 0;
while(1) {
/* read frames from the file */
if(av_read_frame(ffmpeg_ctx->fmt_ctx, &(ffmpeg_ctx->pkt)) >= 0) {
bool is_image = false;
/* check if the packet belongs to a stream we are interested in,
* otherwise skip it
*/
if(ffmpeg_ctx->pkt.stream_index == ffmpeg_ctx->video_stream_idx) {
ret = ffmpeg_decode_packet(ffmpeg_ctx->video_dec_ctx,
&(ffmpeg_ctx->pkt), ffmpeg_ctx);
is_image = true;
}
av_packet_unref(&(ffmpeg_ctx->pkt));
if(ret < 0) {
LV_LOG_WARN("video frame is empty %d", ret);
break;
}
/* Used to filter data that is not an image */
if(is_image) {
break;
}
}
else {
ret = -1;
break;
}
}
return ret;
}
struct ffmpeg_context_s * ffmpeg_open_file(const char * path)
{
if(path == NULL || strlen(path) == 0) {
LV_LOG_ERROR("file path is empty");
return NULL;
}
struct ffmpeg_context_s * ffmpeg_ctx = calloc(1, sizeof(struct ffmpeg_context_s));
if(ffmpeg_ctx == NULL) {
LV_LOG_ERROR("ffmpeg_ctx malloc failed");
goto failed;
}
/* open input file, and allocate format context */
if(avformat_open_input(&(ffmpeg_ctx->fmt_ctx), path, NULL, NULL) < 0) {
LV_LOG_ERROR("Could not open source file %s", path);
goto failed;
}
/* retrieve stream information */
if(avformat_find_stream_info(ffmpeg_ctx->fmt_ctx, NULL) < 0) {
LV_LOG_ERROR("Could not find stream information");
goto failed;
}
if(ffmpeg_open_codec_context(
&(ffmpeg_ctx->video_stream_idx),
&(ffmpeg_ctx->video_dec_ctx),
ffmpeg_ctx->fmt_ctx, AVMEDIA_TYPE_VIDEO)
>= 0) {
ffmpeg_ctx->video_stream = ffmpeg_ctx->fmt_ctx->streams[ffmpeg_ctx->video_stream_idx];
ffmpeg_ctx->has_alpha = ffmpeg_pix_fmt_has_alpha(ffmpeg_ctx->video_dec_ctx->pix_fmt);
ffmpeg_ctx->video_dst_pix_fmt = (ffmpeg_ctx->has_alpha ? AV_PIX_FMT_BGRA : AV_PIX_FMT_TRUE_COLOR);
}
#if LV_FFMPEG_AV_DUMP_FORMAT != 0
/* dump input information to stderr */
av_dump_format(ffmpeg_ctx->fmt_ctx, 0, path, 0);
#endif
if(ffmpeg_ctx->video_stream == NULL) {
LV_LOG_ERROR("Could not find video stream in the input, aborting");
goto failed;
}
return ffmpeg_ctx;
failed:
ffmpeg_close(ffmpeg_ctx);
return NULL;
}
static int ffmpeg_image_allocate(struct ffmpeg_context_s * ffmpeg_ctx)
{
int ret;
/* allocate image where the decoded image will be put */
ret = av_image_alloc(
ffmpeg_ctx->video_src_data,
ffmpeg_ctx->video_src_linesize,
ffmpeg_ctx->video_dec_ctx->width,
ffmpeg_ctx->video_dec_ctx->height,
ffmpeg_ctx->video_dec_ctx->pix_fmt,
4);
if(ret < 0) {
LV_LOG_ERROR("Could not allocate src raw video buffer");
return ret;
}
LV_LOG_INFO("alloc video_src_bufsize = %d", ret);
ret = av_image_alloc(
ffmpeg_ctx->video_dst_data,
ffmpeg_ctx->video_dst_linesize,
ffmpeg_ctx->video_dec_ctx->width,
ffmpeg_ctx->video_dec_ctx->height,
ffmpeg_ctx->video_dst_pix_fmt,
4);
if(ret < 0) {
LV_LOG_ERROR("Could not allocate dst raw video buffer");
return ret;
}
LV_LOG_INFO("allocate video_dst_bufsize = %d", ret);
ffmpeg_ctx->frame = av_frame_alloc();
if(ffmpeg_ctx->frame == NULL) {
LV_LOG_ERROR("Could not allocate frame");
return -1;
}
/* initialize packet, set data to NULL, let the demuxer fill it */
av_init_packet(&ffmpeg_ctx->pkt);
ffmpeg_ctx->pkt.data = NULL;
ffmpeg_ctx->pkt.size = 0;
return 0;
}
static void ffmpeg_close_src_ctx(struct ffmpeg_context_s * ffmpeg_ctx)
{
avcodec_free_context(&(ffmpeg_ctx->video_dec_ctx));
avformat_close_input(&(ffmpeg_ctx->fmt_ctx));
av_frame_free(&(ffmpeg_ctx->frame));
if(ffmpeg_ctx->video_src_data[0] != NULL) {
av_free(ffmpeg_ctx->video_src_data[0]);
ffmpeg_ctx->video_src_data[0] = NULL;
}
}
static void ffmpeg_close_dst_ctx(struct ffmpeg_context_s * ffmpeg_ctx)
{
if(ffmpeg_ctx->video_dst_data[0] != NULL) {
av_free(ffmpeg_ctx->video_dst_data[0]);
ffmpeg_ctx->video_dst_data[0] = NULL;
}
}
static void ffmpeg_close(struct ffmpeg_context_s * ffmpeg_ctx)
{
if(ffmpeg_ctx == NULL) {
LV_LOG_WARN("ffmpeg_ctx is NULL");
return;
}
sws_freeContext(ffmpeg_ctx->sws_ctx);
ffmpeg_close_src_ctx(ffmpeg_ctx);
ffmpeg_close_dst_ctx(ffmpeg_ctx);
free(ffmpeg_ctx);
LV_LOG_INFO("ffmpeg_ctx closed");
}
static void lv_ffmpeg_player_frame_update_cb(lv_timer_t * timer)
{
lv_obj_t * obj = (lv_obj_t *)timer->user_data;
lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj;
if(!player->ffmpeg_ctx) {
return;
}
int has_next = ffmpeg_update_next_frame(player->ffmpeg_ctx);
if(has_next < 0) {
lv_ffmpeg_player_set_cmd(obj, player->auto_restart ? LV_FFMPEG_PLAYER_CMD_START : LV_FFMPEG_PLAYER_CMD_STOP);
return;
}
#if LV_COLOR_DEPTH != 32
if(player->ffmpeg_ctx->has_alpha) {
convert_color_depth((uint8_t *)(player->imgdsc.data),
player->imgdsc.header.w * player->imgdsc.header.h);
}
#endif
lv_img_cache_invalidate_src(lv_img_get_src(obj));
lv_obj_invalidate(obj);
}
static void lv_ffmpeg_player_constructor(const lv_obj_class_t * class_p,
lv_obj_t * obj)
{
LV_TRACE_OBJ_CREATE("begin");
lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj;
player->auto_restart = false;
player->ffmpeg_ctx = NULL;
player->timer = lv_timer_create(lv_ffmpeg_player_frame_update_cb,
FRAME_DEF_REFR_PERIOD, obj);
lv_timer_pause(player->timer);
LV_TRACE_OBJ_CREATE("finished");
}
static void lv_ffmpeg_player_destructor(const lv_obj_class_t * class_p,
lv_obj_t * obj)
{
LV_TRACE_OBJ_CREATE("begin");
lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj;
if(player->timer) {
lv_timer_del(player->timer);
player->timer = NULL;
}
lv_img_cache_invalidate_src(lv_img_get_src(obj));
ffmpeg_close(player->ffmpeg_ctx);
player->ffmpeg_ctx = NULL;
LV_TRACE_OBJ_CREATE("finished");
}
#endif /*LV_USE_FFMPEG*/

View File

@ -0,0 +1,104 @@
/**
* @file lv_ffmpeg.h
*
*/
#ifndef LV_FFMPEG_H
#define LV_FFMPEG_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_FFMPEG != 0
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct ffmpeg_context_s;
extern const lv_obj_class_t lv_ffmpeg_player_class;
typedef struct {
lv_img_t img;
lv_timer_t * timer;
lv_img_dsc_t imgdsc;
bool auto_restart;
struct ffmpeg_context_s * ffmpeg_ctx;
} lv_ffmpeg_player_t;
typedef enum {
LV_FFMPEG_PLAYER_CMD_START,
LV_FFMPEG_PLAYER_CMD_STOP,
LV_FFMPEG_PLAYER_CMD_PAUSE,
LV_FFMPEG_PLAYER_CMD_RESUME,
_LV_FFMPEG_PLAYER_CMD_LAST
} lv_ffmpeg_player_cmd_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Register FFMPEG image decoder
*/
void lv_ffmpeg_init(void);
/**
* Get the number of frames contained in the file
* @param path image or video file name
* @return Number of frames, less than 0 means failed
*/
int lv_ffmpeg_get_frame_num(const char * path);
/**
* Create ffmpeg_player object
* @param parent pointer to an object, it will be the parent of the new player
* @return pointer to the created ffmpeg_player
*/
lv_obj_t * lv_ffmpeg_player_create(lv_obj_t * parent);
/**
* Set the path of the file to be played
* @param obj pointer to a ffmpeg_player object
* @param path video file path
* @return LV_RES_OK: no error; LV_RES_INV: can't get the info.
*/
lv_res_t lv_ffmpeg_player_set_src(lv_obj_t * obj, const char * path);
/**
* Set command control video player
* @param obj pointer to a ffmpeg_player object
* @param cmd control commands
*/
void lv_ffmpeg_player_set_cmd(lv_obj_t * obj, lv_ffmpeg_player_cmd_t cmd);
/**
* Set the video to automatically replay
* @param obj pointer to a ffmpeg_player object
* @param en true: enable the auto restart
*/
void lv_ffmpeg_player_set_auto_restart(lv_obj_t * obj, bool en);
/*=====================
* Other functions
*====================*/
/**********************
* MACROS
**********************/
#endif /*LV_USE_FFMPEG*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_FFMPEG_H*/

View File

@ -0,0 +1,687 @@
/**
* @file lv_freetype.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_freetype.h"
#if LV_USE_FREETYPE
#include "ft2build.h"
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_CACHE_H
#include FT_SIZES_H
#include FT_IMAGE_H
#include FT_OUTLINE_H
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_ll_t face_ll;
} lv_faces_control_t;
typedef struct name_refer_t {
const char * name; /* point to font name string */
int32_t cnt; /* reference count */
} name_refer_t;
typedef struct {
const void * mem;
const char * name;
size_t mem_size;
#if LV_FREETYPE_CACHE_SIZE < 0
FT_Size size;
#endif
lv_font_t * font;
uint16_t style;
uint16_t height;
} lv_font_fmt_ft_dsc_t;
/**********************
* STATIC PROTOTYPES
**********************/
#if LV_FREETYPE_CACHE_SIZE >= 0
static FT_Error font_face_requester(FTC_FaceID face_id,
FT_Library library_is, FT_Pointer req_data, FT_Face * aface);
static bool lv_ft_font_init_cache(lv_ft_info_t * info);
static void lv_ft_font_destroy_cache(lv_font_t * font);
#else
static FT_Face face_find_in_list(lv_ft_info_t * info);
static void face_add_to_list(FT_Face face);
static void face_remove_from_list(FT_Face face);
static void face_generic_finalizer(void * object);
static bool lv_ft_font_init_nocache(lv_ft_info_t * info);
static void lv_ft_font_destroy_nocache(lv_font_t * font);
#endif
static const char * name_refer_save(const char * name);
static void name_refer_del(const char * name);
static const char * name_refer_find(const char * name);
/**********************
* STATIC VARIABLES
**********************/
static FT_Library library;
static lv_ll_t names_ll;
#if LV_FREETYPE_CACHE_SIZE >= 0
static FTC_Manager cache_manager;
static FTC_CMapCache cmap_cache;
static FT_Face current_face = NULL;
#if LV_FREETYPE_SBIT_CACHE
static FTC_SBitCache sbit_cache;
static FTC_SBit sbit;
#else
static FTC_ImageCache image_cache;
static FT_Glyph image_glyph;
#endif
#else
static lv_faces_control_t face_control;
#endif
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
bool lv_freetype_init(uint16_t max_faces, uint16_t max_sizes, uint32_t max_bytes)
{
FT_Error error = FT_Init_FreeType(&library);
if(error) {
LV_LOG_ERROR("init freeType error(%d)", error);
return false;
}
_lv_ll_init(&names_ll, sizeof(name_refer_t));
#if LV_FREETYPE_CACHE_SIZE >= 0
error = FTC_Manager_New(library, max_faces, max_sizes,
max_bytes, font_face_requester, NULL, &cache_manager);
if(error) {
FT_Done_FreeType(library);
LV_LOG_ERROR("Failed to open cache manager");
return false;
}
error = FTC_CMapCache_New(cache_manager, &cmap_cache);
if(error) {
LV_LOG_ERROR("Failed to open Cmap Cache");
goto Fail;
}
#if LV_FREETYPE_SBIT_CACHE
error = FTC_SBitCache_New(cache_manager, &sbit_cache);
if(error) {
LV_LOG_ERROR("Failed to open sbit cache");
goto Fail;
}
#else
error = FTC_ImageCache_New(cache_manager, &image_cache);
if(error) {
LV_LOG_ERROR("Failed to open image cache");
goto Fail;
}
#endif
return true;
Fail:
FTC_Manager_Done(cache_manager);
FT_Done_FreeType(library);
return false;
#else
LV_UNUSED(max_faces);
LV_UNUSED(max_sizes);
LV_UNUSED(max_bytes);
_lv_ll_init(&face_control.face_ll, sizeof(FT_Face *));
return true;
#endif/* LV_FREETYPE_CACHE_SIZE */
}
void lv_freetype_destroy(void)
{
#if LV_FREETYPE_CACHE_SIZE >= 0
FTC_Manager_Done(cache_manager);
#endif
FT_Done_FreeType(library);
}
bool lv_ft_font_init(lv_ft_info_t * info)
{
#if LV_FREETYPE_CACHE_SIZE >= 0
return lv_ft_font_init_cache(info);
#else
return lv_ft_font_init_nocache(info);
#endif
}
void lv_ft_font_destroy(lv_font_t * font)
{
#if LV_FREETYPE_CACHE_SIZE >= 0
lv_ft_font_destroy_cache(font);
#else
lv_ft_font_destroy_nocache(font);
#endif
}
/**********************
* STATIC FUNCTIONS
**********************/
#if LV_FREETYPE_CACHE_SIZE >= 0
static FT_Error font_face_requester(FTC_FaceID face_id,
FT_Library library_is, FT_Pointer req_data, FT_Face * aface)
{
LV_UNUSED(library_is);
LV_UNUSED(req_data);
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)face_id;
FT_Error error;
if(dsc->mem) {
error = FT_New_Memory_Face(library, dsc->mem, dsc->mem_size, 0, aface);
}
else {
error = FT_New_Face(library, dsc->name, 0, aface);
}
if(error) {
LV_LOG_ERROR("FT_New_Face error:%d\n", error);
return error;
}
return FT_Err_Ok;
}
static bool get_bold_glyph(const lv_font_t * font, FT_Face face,
FT_UInt glyph_index, lv_font_glyph_dsc_t * dsc_out)
{
if(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT)) {
return false;
}
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc);
if(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
if(dsc->style & FT_FONT_STYLE_BOLD) {
int strength = 1 << 6;
FT_Outline_Embolden(&face->glyph->outline, strength);
}
}
if(FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL)) {
return false;
}
dsc_out->adv_w = (face->glyph->metrics.horiAdvance >> 6);
dsc_out->box_h = face->glyph->bitmap.rows; /*Height of the bitmap in [px]*/
dsc_out->box_w = face->glyph->bitmap.width; /*Width of the bitmap in [px]*/
dsc_out->ofs_x = face->glyph->bitmap_left; /*X offset of the bitmap in [pf]*/
dsc_out->ofs_y = face->glyph->bitmap_top -
face->glyph->bitmap.rows; /*Y offset of the bitmap measured from the as line*/
dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/
return true;
}
static bool get_glyph_dsc_cb_cache(const lv_font_t * font,
lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next)
{
LV_UNUSED(unicode_letter_next);
if(unicode_letter < 0x20) {
dsc_out->adv_w = 0;
dsc_out->box_h = 0;
dsc_out->box_w = 0;
dsc_out->ofs_x = 0;
dsc_out->ofs_y = 0;
dsc_out->bpp = 0;
return true;
}
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc);
FTC_FaceID face_id = (FTC_FaceID)dsc;
FT_Size face_size;
struct FTC_ScalerRec_ scaler;
scaler.face_id = face_id;
scaler.width = dsc->height;
scaler.height = dsc->height;
scaler.pixel = 1;
if(FTC_Manager_LookupSize(cache_manager, &scaler, &face_size) != 0) {
return false;
}
FT_Face face = face_size->face;
FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap);
FT_UInt glyph_index = FTC_CMapCache_Lookup(cmap_cache, face_id, charmap_index, unicode_letter);
dsc_out->is_placeholder = glyph_index == 0;
if(dsc->style & FT_FONT_STYLE_ITALIC) {
FT_Matrix italic_matrix;
italic_matrix.xx = 1 << 16;
italic_matrix.xy = 0x5800;
italic_matrix.yx = 0;
italic_matrix.yy = 1 << 16;
FT_Set_Transform(face, &italic_matrix, NULL);
}
if(dsc->style & FT_FONT_STYLE_BOLD) {
current_face = face;
if(!get_bold_glyph(font, face, glyph_index, dsc_out)) {
current_face = NULL;
return false;
}
goto end;
}
FTC_ImageTypeRec desc_type;
desc_type.face_id = face_id;
desc_type.flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
desc_type.height = dsc->height;
desc_type.width = dsc->height;
#if LV_FREETYPE_SBIT_CACHE
FT_Error error = FTC_SBitCache_Lookup(sbit_cache, &desc_type, glyph_index, &sbit, NULL);
if(error) {
LV_LOG_ERROR("SBitCache_Lookup error");
return false;
}
dsc_out->adv_w = sbit->xadvance;
dsc_out->box_h = sbit->height; /*Height of the bitmap in [px]*/
dsc_out->box_w = sbit->width; /*Width of the bitmap in [px]*/
dsc_out->ofs_x = sbit->left; /*X offset of the bitmap in [pf]*/
dsc_out->ofs_y = sbit->top - sbit->height; /*Y offset of the bitmap measured from the as line*/
dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/
#else
FT_Error error = FTC_ImageCache_Lookup(image_cache, &desc_type, glyph_index, &image_glyph, NULL);
if(error) {
LV_LOG_ERROR("ImageCache_Lookup error");
return false;
}
if(image_glyph->format != FT_GLYPH_FORMAT_BITMAP) {
LV_LOG_ERROR("Glyph_To_Bitmap error");
return false;
}
FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)image_glyph;
dsc_out->adv_w = (glyph_bitmap->root.advance.x >> 16);
dsc_out->box_h = glyph_bitmap->bitmap.rows; /*Height of the bitmap in [px]*/
dsc_out->box_w = glyph_bitmap->bitmap.width; /*Width of the bitmap in [px]*/
dsc_out->ofs_x = glyph_bitmap->left; /*X offset of the bitmap in [pf]*/
dsc_out->ofs_y = glyph_bitmap->top -
glyph_bitmap->bitmap.rows; /*Y offset of the bitmap measured from the as line*/
dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/
#endif
end:
if((dsc->style & FT_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) {
dsc_out->adv_w = dsc_out->box_w + dsc_out->ofs_x;
}
return true;
}
static const uint8_t * get_glyph_bitmap_cb_cache(const lv_font_t * font, uint32_t unicode_letter)
{
LV_UNUSED(unicode_letter);
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc);
if(dsc->style & FT_FONT_STYLE_BOLD) {
if(current_face && current_face->glyph->format == FT_GLYPH_FORMAT_BITMAP) {
return (const uint8_t *)(current_face->glyph->bitmap.buffer);
}
return NULL;
}
#if LV_FREETYPE_SBIT_CACHE
return (const uint8_t *)sbit->buffer;
#else
FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)image_glyph;
return (const uint8_t *)glyph_bitmap->bitmap.buffer;
#endif
}
static bool lv_ft_font_init_cache(lv_ft_info_t * info)
{
size_t need_size = sizeof(lv_font_fmt_ft_dsc_t) + sizeof(lv_font_t);
lv_font_fmt_ft_dsc_t * dsc = lv_mem_alloc(need_size);
if(dsc == NULL) return false;
lv_memset_00(dsc, need_size);
dsc->font = (lv_font_t *)(((char *)dsc) + sizeof(lv_font_fmt_ft_dsc_t));
dsc->mem = info->mem;
dsc->mem_size = info->mem_size;
dsc->name = name_refer_save(info->name);
dsc->height = info->weight;
dsc->style = info->style;
/* use to get font info */
FT_Size face_size;
struct FTC_ScalerRec_ scaler;
scaler.face_id = (FTC_FaceID)dsc;
scaler.width = info->weight;
scaler.height = info->weight;
scaler.pixel = 1;
FT_Error error = FTC_Manager_LookupSize(cache_manager, &scaler, &face_size);
if(error) {
LV_LOG_ERROR("Failed to LookupSize");
goto Fail;
}
lv_font_t * font = dsc->font;
font->dsc = dsc;
font->get_glyph_dsc = get_glyph_dsc_cb_cache;
font->get_glyph_bitmap = get_glyph_bitmap_cb_cache;
font->subpx = LV_FONT_SUBPX_NONE;
font->line_height = (face_size->face->size->metrics.height >> 6);
font->base_line = -(face_size->face->size->metrics.descender >> 6);
FT_Fixed scale = face_size->face->size->metrics.y_scale;
int8_t thickness = FT_MulFix(scale, face_size->face->underline_thickness) >> 6;
font->underline_position = FT_MulFix(scale, face_size->face->underline_position) >> 6;
font->underline_thickness = thickness < 1 ? 1 : thickness;
/* return to user */
info->font = font;
return true;
Fail:
lv_mem_free(dsc);
return false;
}
void lv_ft_font_destroy_cache(lv_font_t * font)
{
if(font == NULL) {
return;
}
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc);
if(dsc) {
FTC_Manager_RemoveFaceID(cache_manager, (FTC_FaceID)dsc);
name_refer_del(dsc->name);
lv_mem_free(dsc);
}
}
#else/* LV_FREETYPE_CACHE_SIZE */
static FT_Face face_find_in_list(lv_ft_info_t * info)
{
lv_font_fmt_ft_dsc_t * dsc;
FT_Face * pface = _lv_ll_get_head(&face_control.face_ll);
while(pface) {
dsc = (lv_font_fmt_ft_dsc_t *)(*pface)->generic.data;
if(strcmp(dsc->name, info->name) == 0) {
return *pface;
}
pface = _lv_ll_get_next(&face_control.face_ll, pface);
}
return NULL;
}
static void face_add_to_list(FT_Face face)
{
FT_Face * pface;
pface = (FT_Face *)_lv_ll_ins_tail(&face_control.face_ll);
*pface = face;
}
static void face_remove_from_list(FT_Face face)
{
FT_Face * pface = _lv_ll_get_head(&face_control.face_ll);
while(pface) {
if(*pface == face) {
_lv_ll_remove(&face_control.face_ll, pface);
lv_mem_free(pface);
break;
}
pface = _lv_ll_get_next(&face_control.face_ll, pface);
}
}
static void face_generic_finalizer(void * object)
{
FT_Face face = (FT_Face)object;
face_remove_from_list(face);
LV_LOG_INFO("face finalizer(%p)\n", face);
}
static bool get_glyph_dsc_cb_nocache(const lv_font_t * font,
lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next)
{
LV_UNUSED(unicode_letter_next);
if(unicode_letter < 0x20) {
dsc_out->adv_w = 0;
dsc_out->box_h = 0;
dsc_out->box_w = 0;
dsc_out->ofs_x = 0;
dsc_out->ofs_y = 0;
dsc_out->bpp = 0;
return true;
}
FT_Error error;
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc);
FT_Face face = dsc->size->face;
FT_UInt glyph_index = FT_Get_Char_Index(face, unicode_letter);
if(face->size != dsc->size) {
FT_Activate_Size(dsc->size);
}
dsc_out->is_placeholder = glyph_index == 0;
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if(error) {
return false;
}
if(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
if(dsc->style & FT_FONT_STYLE_BOLD) {
int strength = 1 << 6;
FT_Outline_Embolden(&face->glyph->outline, strength);
}
if(dsc->style & FT_FONT_STYLE_ITALIC) {
FT_Matrix italic_matrix;
italic_matrix.xx = 1 << 16;
italic_matrix.xy = 0x5800;
italic_matrix.yx = 0;
italic_matrix.yy = 1 << 16;
FT_Outline_Transform(&face->glyph->outline, &italic_matrix);
}
}
error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
if(error) {
return false;
}
dsc_out->adv_w = (face->glyph->metrics.horiAdvance >> 6);
dsc_out->box_h = face->glyph->bitmap.rows; /*Height of the bitmap in [px]*/
dsc_out->box_w = face->glyph->bitmap.width; /*Width of the bitmap in [px]*/
dsc_out->ofs_x = face->glyph->bitmap_left; /*X offset of the bitmap in [pf]*/
dsc_out->ofs_y = face->glyph->bitmap_top -
face->glyph->bitmap.rows; /*Y offset of the bitmap measured from the as line*/
dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/
if((dsc->style & FT_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) {
dsc_out->adv_w = dsc_out->box_w + dsc_out->ofs_x;
}
return true;
}
static const uint8_t * get_glyph_bitmap_cb_nocache(const lv_font_t * font, uint32_t unicode_letter)
{
LV_UNUSED(unicode_letter);
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc);
FT_Face face = dsc->size->face;
return (const uint8_t *)(face->glyph->bitmap.buffer);
}
static bool lv_ft_font_init_nocache(lv_ft_info_t * info)
{
size_t need_size = sizeof(lv_font_fmt_ft_dsc_t) + sizeof(lv_font_t);
lv_font_fmt_ft_dsc_t * dsc = lv_mem_alloc(need_size);
if(dsc == NULL) return false;
lv_memset_00(dsc, need_size);
dsc->font = (lv_font_t *)(((char *)dsc) + sizeof(lv_font_fmt_ft_dsc_t));
dsc->mem = info->mem;
dsc->mem_size = info->mem_size;
dsc->name = name_refer_save(info->name);
dsc->height = info->weight;
dsc->style = info->style;
FT_Face face = face_find_in_list(info);
if(face == NULL) {
FT_Error error;
if(dsc->mem) {
error = FT_New_Memory_Face(library, dsc->mem, (FT_Long) dsc->mem_size, 0, &face);
}
else {
error = FT_New_Face(library, dsc->name, 0, &face);
}
if(error) {
LV_LOG_WARN("create face error(%d)", error);
goto Fail;
}
/* link face and face info */
face->generic.data = dsc;
face->generic.finalizer = face_generic_finalizer;
face_add_to_list(face);
}
else {
FT_Size size;
FT_Error error = FT_New_Size(face, &size);
if(error) {
goto Fail;
}
FT_Activate_Size(size);
FT_Reference_Face(face);
}
FT_Set_Pixel_Sizes(face, 0, info->weight);
dsc->size = face->size;
lv_font_t * font = dsc->font;
font->dsc = dsc;
font->get_glyph_dsc = get_glyph_dsc_cb_nocache;
font->get_glyph_bitmap = get_glyph_bitmap_cb_nocache;
font->line_height = (face->size->metrics.height >> 6);
font->base_line = -(face->size->metrics.descender >> 6);
font->subpx = LV_FONT_SUBPX_NONE;
FT_Fixed scale = face->size->metrics.y_scale;
int8_t thickness = FT_MulFix(scale, face->underline_thickness) >> 6;
font->underline_position = FT_MulFix(scale, face->underline_position) >> 6;
font->underline_thickness = thickness < 1 ? 1 : thickness;
info->font = font;
return true;
Fail:
lv_mem_free(dsc);
return false;
}
static void lv_ft_font_destroy_nocache(lv_font_t * font)
{
if(font == NULL) {
return;
}
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc);
if(dsc) {
FT_Face face = dsc->size->face;
FT_Done_Size(dsc->size);
FT_Done_Face(face);
name_refer_del(dsc->name);
lv_mem_free(dsc);
}
}
#endif/* LV_FREETYPE_CACHE_SIZE */
/**
* find name string in names list.name string cnt += 1 if find.
* @param name name string
* @return the string pointer of name.
*/
static const char * name_refer_find(const char * name)
{
name_refer_t * refer = _lv_ll_get_head(&names_ll);
while(refer) {
if(strcmp(refer->name, name) == 0) {
refer->cnt += 1;
return refer->name;
}
refer = _lv_ll_get_next(&names_ll, refer);
}
return NULL;
}
/**
* del name string from list.
*/
static void name_refer_del(const char * name)
{
name_refer_t * refer = _lv_ll_get_head(&names_ll);
while(refer) {
if(strcmp(refer->name, name) == 0) {
refer->cnt -= 1;
if(refer->cnt <= 0) {
_lv_ll_remove(&names_ll, refer);
lv_mem_free((void *)refer->name);
lv_mem_free(refer);
}
return;
}
refer = _lv_ll_get_next(&names_ll, refer);
}
LV_LOG_WARN("name_in_names_del error(not find:%p).", name);
}
/**
* save name string to list.
* @param name name string
* @return Saved string pointer
*/
static const char * name_refer_save(const char * name)
{
const char * pos = name_refer_find(name);
if(pos) {
return pos;
}
name_refer_t * refer = _lv_ll_ins_tail(&names_ll);
if(refer) {
uint32_t len = strlen(name) + 1;
refer->name = lv_mem_alloc(len);
if(refer->name) {
lv_memcpy((void *)refer->name, name, len);
refer->cnt = 1;
return refer->name;
}
_lv_ll_remove(&names_ll, refer);
lv_mem_free(refer);
}
LV_LOG_WARN("save_name_to_names error(not memory).");
return "";
}
#endif /*LV_USE_FREETYPE*/

View File

@ -0,0 +1,83 @@
/**
* @file lv_freetype.h
*
*/
#ifndef LV_FREETYPE_H
#define LV_FREETYPE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_FREETYPE
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef enum {
FT_FONT_STYLE_NORMAL = 0,
FT_FONT_STYLE_ITALIC = 1 << 0,
FT_FONT_STYLE_BOLD = 1 << 1
} LV_FT_FONT_STYLE;
typedef struct {
const char * name; /* The name of the font file */
const void * mem; /* The pointer of the font file */
size_t mem_size; /* The size of the memory */
lv_font_t * font; /* point to lvgl font */
uint16_t weight; /* font size */
uint16_t style; /* font style */
} lv_ft_info_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* init freetype library
* @param max_faces Maximum number of opened FT_Face objects managed by this cache instance. Use 0 for defaults.
* @param max_sizes Maximum number of opened FT_Size objects managed by this cache instance. Use 0 for defaults.
* @param max_bytes Maximum number of bytes to use for cached data nodes. Use 0 for defaults.
* Note that this value does not account for managed FT_Face and FT_Size objects.
* @return true on success, otherwise false.
*/
bool lv_freetype_init(uint16_t max_faces, uint16_t max_sizes, uint32_t max_bytes);
/**
* Destroy freetype library
*/
void lv_freetype_destroy(void);
/**
* Creates a font with info parameter specified.
* @param info See lv_ft_info_t for details.
* when success, lv_ft_info_t->font point to the font you created.
* @return true on success, otherwise false.
*/
bool lv_ft_font_init(lv_ft_info_t * info);
/**
* Destroy a font that has been created.
* @param font pointer to font.
*/
void lv_ft_font_destroy(lv_font_t * font);
/**********************
* MACROS
**********************/
#endif /*LV_USE_FREETYPE*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* LV_FREETYPE_H */

View File

@ -0,0 +1,290 @@
/**
* @file lv_fs_fatfs.c
*
*/
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_FS_FATFS
#include "ff.h"
/*********************
* DEFINES
*********************/
#if LV_FS_FATFS_LETTER == '\0'
#error "LV_FS_FATFS_LETTER must be an upper case ASCII letter"
#endif
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void fs_init(void);
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode);
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p);
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw);
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence);
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p);
static void * fs_dir_open(lv_fs_drv_t * drv, const char * path);
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn);
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_fs_fatfs_init(void)
{
/*----------------------------------------------------
* Initialize your storage device and File System
* -------------------------------------------------*/
fs_init();
/*---------------------------------------------------
* Register the file system interface in LVGL
*--------------------------------------------------*/
/*Add a simple drive to open images*/
static lv_fs_drv_t fs_drv; /*A driver descriptor*/
lv_fs_drv_init(&fs_drv);
/*Set up fields...*/
fs_drv.letter = LV_FS_FATFS_LETTER;
fs_drv.cache_size = LV_FS_FATFS_CACHE_SIZE;
fs_drv.open_cb = fs_open;
fs_drv.close_cb = fs_close;
fs_drv.read_cb = fs_read;
fs_drv.write_cb = fs_write;
fs_drv.seek_cb = fs_seek;
fs_drv.tell_cb = fs_tell;
fs_drv.dir_close_cb = fs_dir_close;
fs_drv.dir_open_cb = fs_dir_open;
fs_drv.dir_read_cb = fs_dir_read;
lv_fs_drv_register(&fs_drv);
}
/**********************
* STATIC FUNCTIONS
**********************/
/*Initialize your Storage device and File system.*/
static void fs_init(void)
{
/*Initialize the SD card and FatFS itself.
*Better to do it in your code to keep this library untouched for easy updating*/
}
/**
* Open a file
* @param drv pointer to a driver where this function belongs
* @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt)
* @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR
* @return pointer to FIL struct or NULL in case of fail
*/
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
{
LV_UNUSED(drv);
uint8_t flags = 0;
if(mode == LV_FS_MODE_WR) flags = FA_WRITE | FA_OPEN_ALWAYS;
else if(mode == LV_FS_MODE_RD) flags = FA_READ;
else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = FA_READ | FA_WRITE | FA_OPEN_ALWAYS;
FIL * f = lv_mem_alloc(sizeof(FIL));
if(f == NULL) return NULL;
FRESULT res = f_open(f, path, flags);
if(res == FR_OK) {
return f;
}
else {
lv_mem_free(f);
return NULL;
}
}
/**
* Close an opened file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FIL variable. (opened with fs_open)
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p)
{
LV_UNUSED(drv);
f_close(file_p);
lv_mem_free(file_p);
return LV_FS_RES_OK;
}
/**
* Read data from an opened file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FIL variable.
* @param buf pointer to a memory block where to store the read data
* @param btr number of Bytes To Read
* @param br the real number of read bytes (Byte Read)
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br)
{
LV_UNUSED(drv);
FRESULT res = f_read(file_p, buf, btr, (UINT *)br);
if(res == FR_OK) return LV_FS_RES_OK;
else return LV_FS_RES_UNKNOWN;
}
/**
* Write into a file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FIL variable
* @param buf pointer to a buffer with the bytes to write
* @param btw Bytes To Write
* @param bw the number of real written bytes (Bytes Written). NULL if unused.
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw)
{
LV_UNUSED(drv);
FRESULT res = f_write(file_p, buf, btw, (UINT *)bw);
if(res == FR_OK) return LV_FS_RES_OK;
else return LV_FS_RES_UNKNOWN;
}
/**
* Set the read write pointer. Also expand the file size if necessary.
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FIL variable. (opened with fs_open )
* @param pos the new position of read write pointer
* @param whence only LV_SEEK_SET is supported
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence)
{
LV_UNUSED(drv);
switch(whence) {
case LV_FS_SEEK_SET:
f_lseek(file_p, pos);
break;
case LV_FS_SEEK_CUR:
f_lseek(file_p, f_tell((FIL *)file_p) + pos);
break;
case LV_FS_SEEK_END:
f_lseek(file_p, f_size((FIL *)file_p) + pos);
break;
default:
break;
}
return LV_FS_RES_OK;
}
/**
* Give the position of the read write pointer
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FIL variable.
* @param pos_p pointer to to store the result
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
{
LV_UNUSED(drv);
*pos_p = f_tell((FIL *)file_p);
return LV_FS_RES_OK;
}
/**
* Initialize a 'DIR' variable for directory reading
* @param drv pointer to a driver where this function belongs
* @param path path to a directory
* @return pointer to an initialized 'DIR' variable
*/
static void * fs_dir_open(lv_fs_drv_t * drv, const char * path)
{
LV_UNUSED(drv);
DIR * d = lv_mem_alloc(sizeof(DIR));
if(d == NULL) return NULL;
FRESULT res = f_opendir(d, path);
if(res != FR_OK) {
lv_mem_free(d);
d = NULL;
}
return d;
}
/**
* Read the next filename from a directory.
* The name of the directories will begin with '/'
* @param drv pointer to a driver where this function belongs
* @param dir_p pointer to an initialized 'DIR' variable
* @param fn pointer to a buffer to store the filename
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn)
{
LV_UNUSED(drv);
FRESULT res;
FILINFO fno;
fn[0] = '\0';
do {
res = f_readdir(dir_p, &fno);
if(res != FR_OK) return LV_FS_RES_UNKNOWN;
if(fno.fattrib & AM_DIR) {
fn[0] = '/';
strcpy(&fn[1], fno.fname);
}
else strcpy(fn, fno.fname);
} while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0);
return LV_FS_RES_OK;
}
/**
* Close the directory reading
* @param drv pointer to a driver where this function belongs
* @param dir_p pointer to an initialized 'DIR' variable
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p)
{
LV_UNUSED(drv);
f_closedir(dir_p);
lv_mem_free(dir_p);
return LV_FS_RES_OK;
}
#else /*LV_USE_FS_FATFS == 0*/
#if defined(LV_FS_FATFS_LETTER) && LV_FS_FATFS_LETTER != '\0'
#warning "LV_USE_FS_FATFS is not enabled but LV_FS_FATFS_LETTER is set"
#endif
#endif /*LV_USE_FS_POSIX*/

View File

@ -0,0 +1,319 @@
/**
* @file lv_fs_posix.c
*
*/
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_FS_POSIX
#include <fcntl.h>
#include <stdio.h>
#ifndef WIN32
#include <dirent.h>
#include <unistd.h>
#else
#include <windows.h>
#endif
/*********************
* DEFINES
*********************/
#if LV_FS_POSIX_LETTER == '\0'
#error "LV_FS_POSIX_LETTER must be an upper case ASCII letter"
#endif
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode);
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p);
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw);
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence);
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p);
static void * fs_dir_open(lv_fs_drv_t * drv, const char * path);
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn);
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Register a driver for the File system interface
*/
void lv_fs_posix_init(void)
{
/*---------------------------------------------------
* Register the file system interface in LVGL
*--------------------------------------------------*/
/*Add a simple drive to open images*/
static lv_fs_drv_t fs_drv; /*A driver descriptor*/
lv_fs_drv_init(&fs_drv);
/*Set up fields...*/
fs_drv.letter = LV_FS_POSIX_LETTER;
fs_drv.cache_size = LV_FS_POSIX_CACHE_SIZE;
fs_drv.open_cb = fs_open;
fs_drv.close_cb = fs_close;
fs_drv.read_cb = fs_read;
fs_drv.write_cb = fs_write;
fs_drv.seek_cb = fs_seek;
fs_drv.tell_cb = fs_tell;
fs_drv.dir_close_cb = fs_dir_close;
fs_drv.dir_open_cb = fs_dir_open;
fs_drv.dir_read_cb = fs_dir_read;
lv_fs_drv_register(&fs_drv);
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Open a file
* @param drv pointer to a driver where this function belongs
* @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt)
* @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR
* @return a file handle or -1 in case of fail
*/
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
{
LV_UNUSED(drv);
uint32_t flags = 0;
if(mode == LV_FS_MODE_WR) flags = O_WRONLY | O_CREAT;
else if(mode == LV_FS_MODE_RD) flags = O_RDONLY;
else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = O_RDWR | O_CREAT;
/*Make the path relative to the current directory (the projects root folder)*/
char buf[256];
lv_snprintf(buf, sizeof(buf), LV_FS_POSIX_PATH "%s", path);
int f = open(buf, flags, 0666);
if(f < 0) return NULL;
return (void *)(lv_uintptr_t)f;
}
/**
* Close an opened file
* @param drv pointer to a driver where this function belongs
* @param file_p a file handle. (opened with fs_open)
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p)
{
LV_UNUSED(drv);
close((lv_uintptr_t)file_p);
return LV_FS_RES_OK;
}
/**
* Read data from an opened file
* @param drv pointer to a driver where this function belongs
* @param file_p a file handle variable.
* @param buf pointer to a memory block where to store the read data
* @param btr number of Bytes To Read
* @param br the real number of read bytes (Byte Read)
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br)
{
LV_UNUSED(drv);
*br = read((lv_uintptr_t)file_p, buf, btr);
return (int32_t)(*br) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
}
/**
* Write into a file
* @param drv pointer to a driver where this function belongs
* @param file_p a file handle variable
* @param buf pointer to a buffer with the bytes to write
* @param btw Bytes To Write
* @param bw the number of real written bytes (Bytes Written). NULL if unused.
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw)
{
LV_UNUSED(drv);
*bw = write((lv_uintptr_t)file_p, buf, btw);
return (int32_t)(*bw) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
}
/**
* Set the read write pointer. Also expand the file size if necessary.
* @param drv pointer to a driver where this function belongs
* @param file_p a file handle variable. (opened with fs_open )
* @param pos the new position of read write pointer
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence)
{
LV_UNUSED(drv);
off_t offset = lseek((lv_uintptr_t)file_p, pos, whence);
return offset < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK;
}
/**
* Give the position of the read write pointer
* @param drv pointer to a driver where this function belongs
* @param file_p a file handle variable.
* @param pos_p pointer to to store the result
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
{
LV_UNUSED(drv);
off_t offset = lseek((lv_uintptr_t)file_p, 0, SEEK_CUR);
*pos_p = offset;
return offset < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK;
}
#ifdef WIN32
static char next_fn[256];
#endif
/**
* Initialize a 'fs_read_dir_t' variable for directory reading
* @param drv pointer to a driver where this function belongs
* @param path path to a directory
* @return pointer to an initialized 'DIR' or 'HANDLE' variable
*/
static void * fs_dir_open(lv_fs_drv_t * drv, const char * path)
{
LV_UNUSED(drv);
#ifndef WIN32
/*Make the path relative to the current directory (the projects root folder)*/
char buf[256];
lv_snprintf(buf, sizeof(buf), LV_FS_POSIX_PATH "%s", path);
return opendir(buf);
#else
HANDLE d = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA fdata;
/*Make the path relative to the current directory (the projects root folder)*/
char buf[256];
lv_snprintf(buf, sizeof(buf), LV_FS_POSIX_PATH "%s\\*", path);
strcpy(next_fn, "");
d = FindFirstFile(buf, &fdata);
do {
if(strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) {
continue;
}
else {
if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
sprintf(next_fn, "/%s", fdata.cFileName);
}
else {
sprintf(next_fn, "%s", fdata.cFileName);
}
break;
}
} while(FindNextFileA(d, &fdata));
return d;
#endif
}
/**
* Read the next filename from a directory.
* The name of the directories will begin with '/'
* @param drv pointer to a driver where this function belongs
* @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable
* @param fn pointer to a buffer to store the filename
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn)
{
LV_UNUSED(drv);
#ifndef WIN32
struct dirent * entry;
do {
entry = readdir(dir_p);
if(entry) {
if(entry->d_type == DT_DIR) sprintf(fn, "/%s", entry->d_name);
else strcpy(fn, entry->d_name);
}
else {
strcpy(fn, "");
}
} while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0);
#else
strcpy(fn, next_fn);
strcpy(next_fn, "");
WIN32_FIND_DATA fdata;
if(FindNextFile(dir_p, &fdata) == false) return LV_FS_RES_OK;
do {
if(strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) {
continue;
}
else {
if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
sprintf(next_fn, "/%s", fdata.cFileName);
}
else {
sprintf(next_fn, "%s", fdata.cFileName);
}
break;
}
} while(FindNextFile(dir_p, &fdata));
#endif
return LV_FS_RES_OK;
}
/**
* Close the directory reading
* @param drv pointer to a driver where this function belongs
* @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p)
{
LV_UNUSED(drv);
#ifndef WIN32
closedir(dir_p);
#else
FindClose(dir_p);
#endif
return LV_FS_RES_OK;
}
#else /*LV_USE_FS_POSIX == 0*/
#if defined(LV_FS_POSIX_LETTER) && LV_FS_POSIX_LETTER != '\0'
#warning "LV_USE_FS_POSIX is not enabled but LV_FS_POSIX_LETTER is set"
#endif
#endif /*LV_USE_FS_POSIX*/

View File

@ -0,0 +1,329 @@
/**
* @file lv_fs_stdio.c
*
*/
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_FS_STDIO != '\0'
#include <stdio.h>
#ifndef WIN32
#include <dirent.h>
#include <unistd.h>
#else
#include <windows.h>
#endif
/*********************
* DEFINES
*********************/
#define MAX_PATH_LEN 256
/**********************
* TYPEDEFS
**********************/
typedef struct {
#ifdef WIN32
HANDLE dir_p;
char next_fn[MAX_PATH_LEN];
#else
DIR * dir_p;
#endif
} dir_handle_t;
/**********************
* STATIC PROTOTYPES
**********************/
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode);
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p);
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw);
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence);
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p);
static void * fs_dir_open(lv_fs_drv_t * drv, const char * path);
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn);
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Register a driver for the File system interface
*/
void lv_fs_stdio_init(void)
{
/*---------------------------------------------------
* Register the file system interface in LVGL
*--------------------------------------------------*/
/*Add a simple drive to open images*/
static lv_fs_drv_t fs_drv; /*A driver descriptor*/
lv_fs_drv_init(&fs_drv);
/*Set up fields...*/
fs_drv.letter = LV_FS_STDIO_LETTER;
fs_drv.cache_size = LV_FS_STDIO_CACHE_SIZE;
fs_drv.open_cb = fs_open;
fs_drv.close_cb = fs_close;
fs_drv.read_cb = fs_read;
fs_drv.write_cb = fs_write;
fs_drv.seek_cb = fs_seek;
fs_drv.tell_cb = fs_tell;
fs_drv.dir_close_cb = fs_dir_close;
fs_drv.dir_open_cb = fs_dir_open;
fs_drv.dir_read_cb = fs_dir_read;
lv_fs_drv_register(&fs_drv);
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Open a file
* @param drv pointer to a driver where this function belongs
* @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt)
* @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR
* @return pointer to FIL struct or NULL in case of fail
*/
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
{
LV_UNUSED(drv);
const char * flags = "";
if(mode == LV_FS_MODE_WR) flags = "wb";
else if(mode == LV_FS_MODE_RD) flags = "rb";
else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = "rb+";
/*Make the path relative to the current directory (the projects root folder)*/
char buf[MAX_PATH_LEN];
lv_snprintf(buf, sizeof(buf), LV_FS_STDIO_PATH "%s", path);
return fopen(buf, flags);
}
/**
* Close an opened file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable. (opened with fs_open)
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p)
{
LV_UNUSED(drv);
fclose(file_p);
return LV_FS_RES_OK;
}
/**
* Read data from an opened file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable.
* @param buf pointer to a memory block where to store the read data
* @param btr number of Bytes To Read
* @param br the real number of read bytes (Byte Read)
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br)
{
LV_UNUSED(drv);
*br = fread(buf, 1, btr, file_p);
return (int32_t)(*br) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
}
/**
* Write into a file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable
* @param buf pointer to a buffer with the bytes to write
* @param btw Bytes To Write
* @param bw the number of real written bytes (Bytes Written). NULL if unused.
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw)
{
LV_UNUSED(drv);
*bw = fwrite(buf, 1, btw, file_p);
return (int32_t)(*bw) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
}
/**
* Set the read write pointer. Also expand the file size if necessary.
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable. (opened with fs_open )
* @param pos the new position of read write pointer
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence)
{
LV_UNUSED(drv);
fseek(file_p, pos, whence);
return LV_FS_RES_OK;
}
/**
* Give the position of the read write pointer
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable.
* @param pos_p pointer to to store the result
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
{
LV_UNUSED(drv);
*pos_p = ftell(file_p);
return LV_FS_RES_OK;
}
/**
* Initialize a 'DIR' or 'HANDLE' variable for directory reading
* @param drv pointer to a driver where this function belongs
* @param path path to a directory
* @return pointer to an initialized 'DIR' or 'HANDLE' variable
*/
static void * fs_dir_open(lv_fs_drv_t * drv, const char * path)
{
LV_UNUSED(drv);
dir_handle_t * handle = (dir_handle_t *)lv_mem_alloc(sizeof(dir_handle_t));
#ifndef WIN32
/*Make the path relative to the current directory (the projects root folder)*/
char buf[MAX_PATH_LEN];
lv_snprintf(buf, sizeof(buf), LV_FS_STDIO_PATH "%s", path);
handle->dir_p = opendir(buf);
if(handle->dir_p == NULL) {
lv_mem_free(handle);
return NULL;
}
return handle;
#else
handle->dir_p = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAA fdata;
/*Make the path relative to the current directory (the projects root folder)*/
char buf[MAX_PATH_LEN];
lv_snprintf(buf, sizeof(buf), LV_FS_STDIO_PATH "%s\\*", path);
strcpy(handle->next_fn, "");
handle->dir_p = FindFirstFileA(buf, &fdata);
do {
if(strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) {
continue;
}
else {
if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "/%s", fdata.cFileName);
}
else {
lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "%s", fdata.cFileName);
}
break;
}
} while(FindNextFileA(handle->dir_p, &fdata));
if(handle->dir_p == INVALID_HANDLE_VALUE) {
lv_mem_free(handle);
return INVALID_HANDLE_VALUE;
}
return handle;
#endif
}
/**
* Read the next filename form a directory.
* The name of the directories will begin with '/'
* @param drv pointer to a driver where this function belongs
* @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable
* @param fn pointer to a buffer to store the filename
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn)
{
LV_UNUSED(drv);
dir_handle_t * handle = (dir_handle_t *)dir_p;
#ifndef WIN32
struct dirent * entry;
do {
entry = readdir(handle->dir_p);
if(entry) {
if(entry->d_type == DT_DIR) lv_snprintf(fn, MAX_PATH_LEN, "/%s", entry->d_name);
else strcpy(fn, entry->d_name);
}
else {
strcpy(fn, "");
}
} while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0);
#else
strcpy(fn, handle->next_fn);
strcpy(handle->next_fn, "");
WIN32_FIND_DATAA fdata;
if(FindNextFileA(handle->dir_p, &fdata) == false) return LV_FS_RES_OK;
do {
if(strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) {
continue;
}
else {
if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "/%s", fdata.cFileName);
}
else {
lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "%s", fdata.cFileName);
}
break;
}
} while(FindNextFileA(handle->dir_p, &fdata));
#endif
return LV_FS_RES_OK;
}
/**
* Close the directory reading
* @param drv pointer to a driver where this function belongs
* @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p)
{
LV_UNUSED(drv);
dir_handle_t * handle = (dir_handle_t *)dir_p;
#ifndef WIN32
closedir(handle->dir_p);
#else
FindClose(handle->dir_p);
#endif
lv_mem_free(handle);
return LV_FS_RES_OK;
}
#else /*LV_USE_FS_STDIO == 0*/
#if defined(LV_FS_STDIO_LETTER) && LV_FS_STDIO_LETTER != '\0'
#warning "LV_USE_FS_STDIO is not enabled but LV_FS_STDIO_LETTER is set"
#endif
#endif /*LV_USE_FS_POSIX*/

View File

@ -0,0 +1,466 @@
/**
* @file lv_fs_win32.c
*
*/
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_FS_WIN32 != '\0'
#include <windows.h>
#include <stdio.h>
/*********************
* DEFINES
*********************/
#define MAX_PATH_LEN 256
/**********************
* TYPEDEFS
**********************/
typedef struct {
HANDLE dir_p;
char next_fn[MAX_PATH_LEN];
lv_fs_res_t next_error;
} dir_handle_t;
/**********************
* STATIC PROTOTYPES
**********************/
static bool is_dots_name(const char * name);
static lv_fs_res_t fs_error_from_win32(DWORD error);
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode);
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p);
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw);
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence);
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p);
static void * fs_dir_open(lv_fs_drv_t * drv, const char * path);
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn);
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Register a driver for the File system interface
*/
void lv_fs_win32_init(void)
{
/*---------------------------------------------------
* Register the file system interface in LVGL
*--------------------------------------------------*/
/*Add a simple driver to open images*/
static lv_fs_drv_t fs_drv; /*A driver descriptor*/
lv_fs_drv_init(&fs_drv);
/*Set up fields...*/
fs_drv.letter = LV_FS_WIN32_LETTER;
fs_drv.cache_size = LV_FS_WIN32_CACHE_SIZE;
fs_drv.open_cb = fs_open;
fs_drv.close_cb = fs_close;
fs_drv.read_cb = fs_read;
fs_drv.write_cb = fs_write;
fs_drv.seek_cb = fs_seek;
fs_drv.tell_cb = fs_tell;
fs_drv.dir_close_cb = fs_dir_close;
fs_drv.dir_open_cb = fs_dir_open;
fs_drv.dir_read_cb = fs_dir_read;
lv_fs_drv_register(&fs_drv);
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Check the dots name
* @param name file or dir name
* @return true if the name is dots name
*/
static bool is_dots_name(const char * name)
{
return name[0] == '.' && (!name[1] || (name[1] == '.' && !name[2]));
}
/**
* Convert Win32 error code to error from lv_fs_res_t enum
* @param error Win32 error code
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_error_from_win32(DWORD error)
{
lv_fs_res_t res;
switch(error) {
case ERROR_SUCCESS:
res = LV_FS_RES_OK;
break;
case ERROR_BAD_UNIT:
case ERROR_NOT_READY:
case ERROR_CRC:
case ERROR_SEEK:
case ERROR_NOT_DOS_DISK:
case ERROR_WRITE_FAULT:
case ERROR_READ_FAULT:
case ERROR_GEN_FAILURE:
case ERROR_WRONG_DISK:
res = LV_FS_RES_HW_ERR;
break;
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_TARGET_HANDLE:
res = LV_FS_RES_FS_ERR;
break;
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
case ERROR_INVALID_DRIVE:
case ERROR_NO_MORE_FILES:
case ERROR_SECTOR_NOT_FOUND:
case ERROR_BAD_NETPATH:
case ERROR_BAD_NET_NAME:
case ERROR_BAD_PATHNAME:
case ERROR_FILENAME_EXCED_RANGE:
res = LV_FS_RES_NOT_EX;
break;
case ERROR_DISK_FULL:
res = LV_FS_RES_FULL;
break;
case ERROR_SHARING_VIOLATION:
case ERROR_LOCK_VIOLATION:
case ERROR_DRIVE_LOCKED:
res = LV_FS_RES_LOCKED;
break;
case ERROR_ACCESS_DENIED:
case ERROR_CURRENT_DIRECTORY:
case ERROR_WRITE_PROTECT:
case ERROR_NETWORK_ACCESS_DENIED:
case ERROR_CANNOT_MAKE:
case ERROR_FAIL_I24:
case ERROR_SEEK_ON_DEVICE:
case ERROR_NOT_LOCKED:
case ERROR_LOCK_FAILED:
res = LV_FS_RES_DENIED;
break;
case ERROR_BUSY:
res = LV_FS_RES_BUSY;
break;
case ERROR_TIMEOUT:
res = LV_FS_RES_TOUT;
break;
case ERROR_NOT_SAME_DEVICE:
case ERROR_DIRECT_ACCESS_HANDLE:
res = LV_FS_RES_NOT_IMP;
break;
case ERROR_TOO_MANY_OPEN_FILES:
case ERROR_ARENA_TRASHED:
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_INVALID_BLOCK:
case ERROR_OUT_OF_PAPER:
case ERROR_SHARING_BUFFER_EXCEEDED:
case ERROR_NOT_ENOUGH_QUOTA:
res = LV_FS_RES_OUT_OF_MEM;
break;
case ERROR_INVALID_FUNCTION:
case ERROR_INVALID_ACCESS:
case ERROR_INVALID_DATA:
case ERROR_BAD_COMMAND:
case ERROR_BAD_LENGTH:
case ERROR_INVALID_PARAMETER:
case ERROR_NEGATIVE_SEEK:
res = LV_FS_RES_INV_PARAM;
break;
default:
res = LV_FS_RES_UNKNOWN;
break;
}
return res;
}
/**
* Open a file
* @param drv pointer to a driver where this function belongs
* @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt)
* @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR
* @return pointer to FIL struct or NULL in case of fail
*/
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
{
LV_UNUSED(drv);
DWORD desired_access = 0;
if(mode & LV_FS_MODE_RD) {
desired_access |= GENERIC_READ;
}
if(mode & LV_FS_MODE_WR) {
desired_access |= GENERIC_WRITE;
}
/*Make the path relative to the current directory (the projects root folder)*/
char buf[MAX_PATH];
lv_snprintf(buf, sizeof(buf), LV_FS_WIN32_PATH "%s", path);
return (void *)CreateFileA(
buf,
desired_access,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
}
/**
* Close an opened file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable. (opened with fs_open)
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p)
{
LV_UNUSED(drv);
return CloseHandle((HANDLE)file_p)
? LV_FS_RES_OK
: fs_error_from_win32(GetLastError());
}
/**
* Read data from an opened file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable.
* @param buf pointer to a memory block where to store the read data
* @param btr number of Bytes To Read
* @param br the real number of read bytes (Byte Read)
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br)
{
LV_UNUSED(drv);
return ReadFile((HANDLE)file_p, buf, btr, (LPDWORD)br, NULL)
? LV_FS_RES_OK
: fs_error_from_win32(GetLastError());
}
/**
* Write into a file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable
* @param buf pointer to a buffer with the bytes to write
* @param btw Bytes To Write
* @param bw the number of real written bytes (Bytes Written). NULL if unused.
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw)
{
LV_UNUSED(drv);
return WriteFile((HANDLE)file_p, buf, btw, (LPDWORD)bw, NULL)
? LV_FS_RES_OK
: fs_error_from_win32(GetLastError());
}
/**
* Set the read write pointer. Also expand the file size if necessary.
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable. (opened with fs_open )
* @param pos the new position of read write pointer
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence)
{
LV_UNUSED(drv);
DWORD move_method = (DWORD) -1;
if(whence == LV_FS_SEEK_SET) {
move_method = FILE_BEGIN;
}
else if(whence == LV_FS_SEEK_CUR) {
move_method = FILE_CURRENT;
}
else if(whence == LV_FS_SEEK_END) {
move_method = FILE_END;
}
LARGE_INTEGER distance_to_move;
distance_to_move.QuadPart = pos;
return SetFilePointerEx((HANDLE)file_p, distance_to_move, NULL, move_method)
? LV_FS_RES_OK
: fs_error_from_win32(GetLastError());
}
/**
* Give the position of the read write pointer
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable.
* @param pos_p pointer to to store the result
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
{
LV_UNUSED(drv);
if(!pos_p) {
return LV_FS_RES_INV_PARAM;
}
LARGE_INTEGER file_pointer;
file_pointer.QuadPart = 0;
LARGE_INTEGER distance_to_move;
distance_to_move.QuadPart = 0;
if(SetFilePointerEx(
(HANDLE)file_p,
distance_to_move,
&file_pointer,
FILE_CURRENT)) {
if(file_pointer.QuadPart > LONG_MAX) {
return LV_FS_RES_INV_PARAM;
}
else {
*pos_p = file_pointer.LowPart;
return LV_FS_RES_OK;
}
}
else {
return fs_error_from_win32(GetLastError());
}
}
/**
* Initialize a 'DIR' or 'HANDLE' variable for directory reading
* @param drv pointer to a driver where this function belongs
* @param path path to a directory
* @return pointer to an initialized 'DIR' or 'HANDLE' variable
*/
static void * fs_dir_open(lv_fs_drv_t * drv, const char * path)
{
LV_UNUSED(drv);
dir_handle_t * handle = (dir_handle_t *)lv_mem_alloc(sizeof(dir_handle_t));
handle->dir_p = INVALID_HANDLE_VALUE;
handle->next_error = LV_FS_RES_OK;
WIN32_FIND_DATAA fdata;
/*Make the path relative to the current directory (the projects root folder)*/
char buf[MAX_PATH_LEN];
#ifdef LV_FS_WIN32_PATH
lv_snprintf(buf, sizeof(buf), LV_FS_WIN32_PATH "%s\\*", path);
#else
lv_snprintf(buf, sizeof(buf), "%s\\*", path);
#endif
strcpy(handle->next_fn, "");
handle->dir_p = FindFirstFileA(buf, &fdata);
do {
if(is_dots_name(fdata.cFileName)) {
continue;
}
else {
if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "/%s", fdata.cFileName);
}
else {
lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "%s", fdata.cFileName);
}
break;
}
} while(FindNextFileA(handle->dir_p, &fdata));
if(handle->dir_p == INVALID_HANDLE_VALUE) {
lv_mem_free(handle);
handle->next_error = fs_error_from_win32(GetLastError());
return INVALID_HANDLE_VALUE;
}
else {
handle->next_error = LV_FS_RES_OK;
return handle;
}
}
/**
* Read the next filename from a directory.
* The name of the directories will begin with '/'
* @param drv pointer to a driver where this function belongs
* @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable
* @param fn pointer to a buffer to store the filename
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn)
{
LV_UNUSED(drv);
dir_handle_t * handle = (dir_handle_t *)dir_p;
strcpy(fn, handle->next_fn);
lv_fs_res_t current_error = handle->next_error;
strcpy(handle->next_fn, "");
WIN32_FIND_DATAA fdata;
while(FindNextFileA(handle->dir_p, &fdata)) {
if(is_dots_name(fdata.cFileName)) {
continue;
}
else {
if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "/%s", fdata.cFileName);
}
else {
lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "%s", fdata.cFileName);
}
break;
}
}
if(handle->next_fn[0] == '\0') {
handle->next_error = fs_error_from_win32(GetLastError());
}
return current_error;
}
/**
* Close the directory reading
* @param drv pointer to a driver where this function belongs
* @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p)
{
LV_UNUSED(drv);
dir_handle_t * handle = (dir_handle_t *)dir_p;
lv_fs_res_t res = FindClose(handle->dir_p)
? LV_FS_RES_OK
: fs_error_from_win32(GetLastError());
lv_mem_free(handle);
return res;
}
#else /*LV_USE_FS_WIN32 == 0*/
#if defined(LV_FS_WIN32_LETTER) && LV_FS_WIN32_LETTER != '\0'
#warning "LV_USE_FS_WIN32 is not enabled but LV_FS_WIN32_LETTER is set"
#endif
#endif

View File

@ -0,0 +1,55 @@
/**
* @file lv_fsdrv.h
*
*/
#ifndef LV_FSDRV_H
#define LV_FSDRV_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
#if LV_USE_FS_FATFS != '\0'
void lv_fs_fatfs_init(void);
#endif
#if LV_USE_FS_STDIO != '\0'
void lv_fs_stdio_init(void);
#endif
#if LV_USE_FS_POSIX != '\0'
void lv_fs_posix_init(void);
#endif
#if LV_USE_FS_WIN32 != '\0'
void lv_fs_win32_init(void);
#endif
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_FSDRV_H*/

View File

@ -0,0 +1,722 @@
#include "gifdec.h"
#include "../../../misc/lv_log.h"
#include "../../../misc/lv_mem.h"
#include "../../../misc/lv_color.h"
#if LV_USE_GIF
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "lv_conf.h"
#define MIN(A, B) ((A) < (B) ? (A) : (B))
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define LV_GIF_LOG printf
#define GIF_MEM_FRAME 1 //1 frame buffer 0 mem_alloc
typedef struct Entry {
uint16_t length;
uint16_t prefix;
uint8_t suffix;
} Entry;
typedef struct Table {
int bulk;
int nentries;
Entry *entries;
} Table;
static gd_GIF * gif_open(gd_GIF * gif);
static bool f_gif_open(gd_GIF * gif, const void * path, bool is_file);
static void f_gif_read(gd_GIF * gif, void * buf, size_t len);
static int f_gif_seek(gd_GIF * gif, size_t pos, int k);
static void f_gif_close(gd_GIF * gif);
static uint16_t
read_num(gd_GIF * gif)
{
uint8_t bytes[2];
f_gif_read(gif, bytes, 2);
return bytes[0] + (((uint16_t) bytes[1]) << 8);
}
gd_GIF *
gd_open_gif_file(const char *fname)
{
gd_GIF gif_base;
memset(&gif_base, 0, sizeof(gif_base));
bool res = f_gif_open(&gif_base, fname, true);
if(!res) return NULL;
return gif_open(&gif_base);
}
gd_GIF *
gd_open_gif_data(const void *data)
{
gd_GIF gif_base;
memset(&gif_base, 0, sizeof(gif_base));
bool res = f_gif_open(&gif_base, data, false);
if(!res) return NULL;
return gif_open(&gif_base);
}
gd_GIF *
gd_open_gif_data_ex(const void *data)
{
gd_GIF gif_base;
memset(&gif_base, 0, sizeof(gif_base));
gif_base.is_file = false;
gif_base.f_rw_p = 0;
memcpy((void*)&gif_base.offset,data,4);
LV_GIF_LOG("offset:%x\n",gif_base.offset);
return gif_open(&gif_base);
}
static gd_GIF * gif_open(gd_GIF * gif_base)
{
uint8_t sigver[3];
uint16_t width, height, depth;
uint8_t fdsz, bgidx, aspect;
int i;
uint8_t *bgcolor;
int gct_sz;
gd_GIF *gif = NULL;
/* Header */
f_gif_read(gif_base, sigver, 3);
if (memcmp(sigver, "GIF", 3) != 0) {
LV_GIF_LOG("invalid signature\n");
goto fail;
}
/* Version */
f_gif_read(gif_base, sigver, 3);
if (memcmp(sigver, "89a", 3) != 0) {
LV_GIF_LOG("invalid version\n");
goto fail;
}
/* Width x Height */
width = read_num(gif_base);
height = read_num(gif_base);
/* FDSZ */
f_gif_read(gif_base, &fdsz, 1);
/* Presence of GCT */
if (!(fdsz & 0x80)) {
LV_GIF_LOG("no global color table\n");
goto fail;
}
/* Color Space's Depth */
depth = ((fdsz >> 4) & 7) + 1;
/* Ignore Sort Flag. */
/* GCT Size */
gct_sz = 1 << ((fdsz & 0x07) + 1);
/* Background Color Index */
f_gif_read(gif_base, &bgidx, 1);
/* Aspect Ratio */
f_gif_read(gif_base, &aspect, 1);
/* Create gd_GIF Structure. */
#if LV_COLOR_DEPTH == 32
gif = lv_mem_alloc(sizeof(gd_GIF) + 5 * width * height);
#elif LV_COLOR_DEPTH == 16
#if (GIF_MEM_FRAME==1)
extern uint32_t *user_get_display_framebuffer(void);
gif = (void*)user_get_display_framebuffer();
#else
gif = lv_mem_alloc(sizeof(gd_GIF) + 4 * width * height);
#endif
#elif LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1
gif = lv_mem_alloc(sizeof(gd_GIF) + 3 * width * height);
#endif
if (!gif) goto fail;
memcpy(gif, gif_base, sizeof(gd_GIF));
gif->width = width;
gif->height = height;
gif->depth = depth;
/* Read GCT */
gif->gct.size = gct_sz;
f_gif_read(gif, gif->gct.colors, 3 * gif->gct.size);
gif->palette = &gif->gct;
gif->bgindex = bgidx;
gif->canvas = (uint8_t *) &gif[1];
#if LV_COLOR_DEPTH == 32
gif->frame = &gif->canvas[4 * width * height];
#elif LV_COLOR_DEPTH == 16
gif->frame = &gif->canvas[3 * width * height];
#elif LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1
gif->frame = &gif->canvas[2 * width * height];
#endif
if (gif->bgindex) {
memset(gif->frame, gif->bgindex, gif->width * gif->height);
}
bgcolor = &gif->palette->colors[gif->bgindex*3];
for (i = 0; i < gif->width * gif->height; i++) {
#if LV_COLOR_DEPTH == 32
gif->canvas[i*4 + 0] = *(bgcolor + 2);
gif->canvas[i*4 + 1] = *(bgcolor + 1);
gif->canvas[i*4 + 2] = *(bgcolor + 0);
gif->canvas[i*4 + 3] = 0xff;
#elif LV_COLOR_DEPTH == 16
lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2));
gif->canvas[i*3 + 0] = c.full & 0xff;
gif->canvas[i*3 + 1] = (c.full >> 8) & 0xff;
gif->canvas[i*3 + 2] = 0xff;
#elif LV_COLOR_DEPTH == 8
lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2));
gif->canvas[i*2 + 0] = c.full;
gif->canvas[i*2 + 1] = 0xff;
#elif LV_COLOR_DEPTH == 1
lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2));
gif->canvas[i*2 + 0] = c.ch.red > 128 ? 1 : 0;
gif->canvas[i*2 + 1] = 0xff;
#endif
}
gif->anim_start = f_gif_seek(gif, 0, LV_FS_SEEK_CUR);
gif->loop_count = -1;
goto ok;
fail:
f_gif_close(gif_base);
ok:
return gif;
}
static void
discard_sub_blocks(gd_GIF *gif)
{
uint8_t size;
do {
f_gif_read(gif, &size, 1);
f_gif_seek(gif, size, LV_FS_SEEK_CUR);
} while (size);
}
static void
read_plain_text_ext(gd_GIF *gif)
{
if (gif->plain_text) {
uint16_t tx, ty, tw, th;
uint8_t cw, ch, fg, bg;
size_t sub_block;
f_gif_seek(gif, 1, LV_FS_SEEK_CUR); /* block size = 12 */
tx = read_num(gif);
ty = read_num(gif);
tw = read_num(gif);
th = read_num(gif);
f_gif_read(gif, &cw, 1);
f_gif_read(gif, &ch, 1);
f_gif_read(gif, &fg, 1);
f_gif_read(gif, &bg, 1);
sub_block = f_gif_seek(gif, 0, LV_FS_SEEK_CUR);
gif->plain_text(gif, tx, ty, tw, th, cw, ch, fg, bg);
f_gif_seek(gif, sub_block, LV_FS_SEEK_SET);
} else {
/* Discard plain text metadata. */
f_gif_seek(gif, 13, LV_FS_SEEK_CUR);
}
/* Discard plain text sub-blocks. */
discard_sub_blocks(gif);
}
static void
read_graphic_control_ext(gd_GIF *gif)
{
uint8_t rdit;
/* Discard block size (always 0x04). */
f_gif_seek(gif, 1, LV_FS_SEEK_CUR);
f_gif_read(gif, &rdit, 1);
gif->gce.disposal = (rdit >> 2) & 3;
gif->gce.input = rdit & 2;
gif->gce.transparency = rdit & 1;
gif->gce.delay = read_num(gif);
f_gif_read(gif, &gif->gce.tindex, 1);
/* Skip block terminator. */
f_gif_seek(gif, 1, LV_FS_SEEK_CUR);
}
static void
read_comment_ext(gd_GIF *gif)
{
if (gif->comment) {
size_t sub_block = f_gif_seek(gif, 0, LV_FS_SEEK_CUR);
gif->comment(gif);
f_gif_seek(gif, sub_block, LV_FS_SEEK_SET);
}
/* Discard comment sub-blocks. */
discard_sub_blocks(gif);
}
static void
read_application_ext(gd_GIF *gif)
{
char app_id[8];
char app_auth_code[3];
uint16_t loop_count;
/* Discard block size (always 0x0B). */
f_gif_seek(gif, 1, LV_FS_SEEK_CUR);
/* Application Identifier. */
f_gif_read(gif, app_id, 8);
/* Application Authentication Code. */
f_gif_read(gif, app_auth_code, 3);
if (!strncmp(app_id, "NETSCAPE", sizeof(app_id))) {
/* Discard block size (0x03) and constant byte (0x01). */
f_gif_seek(gif, 2, LV_FS_SEEK_CUR);
loop_count = read_num(gif);
if(gif->loop_count < 0) {
if(loop_count == 0) {
gif->loop_count = 0;
}
else{
gif->loop_count = loop_count + 1;
}
}
/* Skip block terminator. */
f_gif_seek(gif, 1, LV_FS_SEEK_CUR);
} else if (gif->application) {
size_t sub_block = f_gif_seek(gif, 0, LV_FS_SEEK_CUR);
gif->application(gif, app_id, app_auth_code);
f_gif_seek(gif, sub_block, LV_FS_SEEK_SET);
discard_sub_blocks(gif);
} else {
discard_sub_blocks(gif);
}
}
static void
read_ext(gd_GIF *gif)
{
uint8_t label;
f_gif_read(gif, &label, 1);
switch (label) {
case 0x01:
read_plain_text_ext(gif);
break;
case 0xF9:
read_graphic_control_ext(gif);
break;
case 0xFE:
read_comment_ext(gif);
break;
case 0xFF:
read_application_ext(gif);
break;
default:
LV_GIF_LOG("unknown extension: %02X\n", label);
}
}
static Table *
new_table(int key_size)
{
int key;
int init_bulk = MAX(1 << (key_size + 1), 0x100);
Table *table = lv_mem_alloc(sizeof(*table) + sizeof(Entry) * init_bulk);
if (table) {
table->bulk = init_bulk;
table->nentries = (1 << key_size) + 2;
table->entries = (Entry *) &table[1];
for (key = 0; key < (1 << key_size); key++)
table->entries[key] = (Entry) {1, 0xFFF, key};
}
return table;
}
/* Add table entry. Return value:
* 0 on success
* +1 if key size must be incremented after this addition
* -1 if could not realloc table */
static int
add_entry(Table **tablep, uint16_t length, uint16_t prefix, uint8_t suffix)
{
Table *table = *tablep;
if (table->nentries == table->bulk) {
table->bulk *= 2;
table = lv_mem_realloc(table, sizeof(*table) + sizeof(Entry) * table->bulk);
if (!table) return -1;
table->entries = (Entry *) &table[1];
*tablep = table;
}
table->entries[table->nentries] = (Entry) {length, prefix, suffix};
table->nentries++;
if ((table->nentries & (table->nentries - 1)) == 0)
return 1;
return 0;
}
static uint16_t
get_key(gd_GIF *gif, int key_size, uint8_t *sub_len, uint8_t *shift, uint8_t *byte)
{
int bits_read;
int rpad;
int frag_size;
uint16_t key;
key = 0;
for (bits_read = 0; bits_read < key_size; bits_read += frag_size) {
rpad = (*shift + bits_read) % 8;
if (rpad == 0) {
/* Update byte. */
if (*sub_len == 0) {
f_gif_read(gif, sub_len, 1); /* Must be nonzero! */
if (*sub_len == 0) return 0x1000;
}
f_gif_read(gif, byte, 1);
(*sub_len)--;
}
frag_size = MIN(key_size - bits_read, 8 - rpad);
key |= ((uint16_t) ((*byte) >> rpad)) << bits_read;
}
/* Clear extra bits to the left. */
key &= (1 << key_size) - 1;
*shift = (*shift + key_size) % 8;
return key;
}
/* Compute output index of y-th input line, in frame of height h. */
static int
interlaced_line_index(int h, int y)
{
int p; /* number of lines in current pass */
p = (h - 1) / 8 + 1;
if (y < p) /* pass 1 */
return y * 8;
y -= p;
p = (h - 5) / 8 + 1;
if (y < p) /* pass 2 */
return y * 8 + 4;
y -= p;
p = (h - 3) / 4 + 1;
if (y < p) /* pass 3 */
return y * 4 + 2;
y -= p;
/* pass 4 */
return y * 2 + 1;
}
/* Decompress image pixels.
* Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table). */
static int
read_image_data(gd_GIF *gif, int interlace)
{
uint8_t sub_len, shift, byte;
int init_key_size, key_size, table_is_full=0;
int frm_off, frm_size, str_len=0, i, p, x, y;
uint16_t key, clear, stop;
int ret;
Table *table;
Entry entry = {0};
size_t start, end;
f_gif_read(gif, &byte, 1);
key_size = (int) byte;
start = f_gif_seek(gif, 0, LV_FS_SEEK_CUR);
discard_sub_blocks(gif);
end = f_gif_seek(gif, 0, LV_FS_SEEK_CUR);
f_gif_seek(gif, start, LV_FS_SEEK_SET);
clear = 1 << key_size;
stop = clear + 1;
table = new_table(key_size);
key_size++;
init_key_size = key_size;
sub_len = shift = 0;
key = get_key(gif, key_size, &sub_len, &shift, &byte); /* clear code */
frm_off = 0;
ret = 0;
frm_size = gif->fw*gif->fh;
while (frm_off < frm_size) {
if (key == clear) {
key_size = init_key_size;
table->nentries = (1 << (key_size - 1)) + 2;
table_is_full = 0;
} else if (!table_is_full) {
ret = add_entry(&table, str_len + 1, key, entry.suffix);
if (ret == -1) {
lv_mem_free(table);
return -1;
}
if (table->nentries == 0x1000) {
ret = 0;
table_is_full = 1;
}
}
key = get_key(gif, key_size, &sub_len, &shift, &byte);
if (key == clear) continue;
if (key == stop || key == 0x1000) break;
if (ret == 1) key_size++;
entry = table->entries[key];
str_len = entry.length;
for (i = 0; i < str_len; i++) {
p = frm_off + entry.length - 1;
x = p % gif->fw;
y = p / gif->fw;
if (interlace)
y = interlaced_line_index((int) gif->fh, y);
gif->frame[(gif->fy + y) * gif->width + gif->fx + x] = entry.suffix;
if (entry.prefix == 0xFFF)
break;
else
entry = table->entries[entry.prefix];
}
frm_off += str_len;
if (key < table->nentries - 1 && !table_is_full)
table->entries[table->nentries - 1].suffix = entry.suffix;
}
lv_mem_free(table);
if (key == stop) f_gif_read(gif, &sub_len, 1); /* Must be zero! */
f_gif_seek(gif, end, LV_FS_SEEK_SET);
return 0;
}
/* Read image.
* Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table). */
static int
read_image(gd_GIF *gif)
{
uint8_t fisrz;
int interlace;
/* Image Descriptor. */
gif->fx = read_num(gif);
gif->fy = read_num(gif);
gif->fw = read_num(gif);
gif->fh = read_num(gif);
f_gif_read(gif, &fisrz, 1);
interlace = fisrz & 0x40;
/* Ignore Sort Flag. */
/* Local Color Table? */
if (fisrz & 0x80) {
/* Read LCT */
gif->lct.size = 1 << ((fisrz & 0x07) + 1);
f_gif_read(gif, gif->lct.colors, 3 * gif->lct.size);
gif->palette = &gif->lct;
} else
gif->palette = &gif->gct;
/* Image Data. */
return read_image_data(gif, interlace);
}
static void
render_frame_rect(gd_GIF *gif, uint8_t *buffer)
{
//LV_GIF_LOG("render_frame_rect\n");
int i, j, k;
uint8_t index, *color;
i = gif->fy * gif->width + gif->fx;
for (j = 0; j < gif->fh; j++) {
for (k = 0; k < gif->fw; k++) {
index = gif->frame[(gif->fy + j) * gif->width + gif->fx + k];
color = &gif->palette->colors[index*3];
if (!gif->gce.transparency || index != gif->gce.tindex) {
#if LV_COLOR_DEPTH == 32
buffer[(i+k)*4 + 0] = *(color + 2);
buffer[(i+k)*4 + 1] = *(color + 1);
buffer[(i+k)*4 + 2] = *(color + 0);
buffer[(i+k)*4 + 3] = 0xFF;
#elif LV_COLOR_DEPTH == 16
lv_color_t c = lv_color_make(*(color + 0), *(color + 1), *(color + 2));
buffer[(i+k)*3 + 0] = c.full & 0xff;
buffer[(i+k)*3 + 1] = (c.full >> 8) & 0xff;
if( c.full==0x00)
{
buffer[(i+k)*3 + 2] = 0x00;//clear background
}else{
buffer[(i+k)*3 + 2] = 0xff;
}
#elif LV_COLOR_DEPTH == 8
lv_color_t c = lv_color_make(*(color + 0), *(color + 1), *(color + 2));
buffer[(i+k)*2 + 0] = c.full;
buffer[(i+k)*2 + 1] = 0xff;
#elif LV_COLOR_DEPTH == 1
uint8_t b = (*(color + 0)) | (*(color + 1)) | (*(color + 2));
buffer[(i+k)*2 + 0] = b > 128 ? 1 : 0;
buffer[(i+k)*2 + 1] = 0xff;
#endif
}
}
i += gif->width;
}
}
static void
dispose(gd_GIF *gif)
{
int i, j, k;
uint8_t *bgcolor;
switch (gif->gce.disposal) {
case 2: /* Restore to background color. */
bgcolor = &gif->palette->colors[gif->bgindex*3];
uint8_t opa = 0xff;
if(gif->gce.transparency) opa = 0x00;
//opa = 0xff;
LV_GIF_LOG("opa :%x\n",opa);
i = gif->fy * gif->width + gif->fx;
for (j = 0; j < gif->fh; j++) {
for (k = 0; k < gif->fw; k++) {
#if LV_COLOR_DEPTH == 32
gif->canvas[(i+k)*4 + 0] = *(bgcolor + 2);
gif->canvas[(i+k)*4 + 1] = *(bgcolor + 1);
gif->canvas[(i+k)*4 + 2] = *(bgcolor + 0);
gif->canvas[(i+k)*4 + 3] = opa;
#elif LV_COLOR_DEPTH == 16
lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2));
gif->canvas[(i+k)*3 + 0] = c.full & 0xff;
gif->canvas[(i+k)*3 + 1] = (c.full >> 8) & 0xff;
gif->canvas[(i+k)*3 + 2] = opa;
#elif LV_COLOR_DEPTH == 8
lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2));
gif->canvas[(i+k)*2 + 0] = c.full;
gif->canvas[(i+k)*2 + 1] = opa;
#elif LV_COLOR_DEPTH == 1
uint8_t b = (*(bgcolor + 0)) | (*(bgcolor + 1)) | (*(bgcolor + 2));
gif->canvas[(i+k)*2 + 0] = b > 128 ? 1 : 0;
gif->canvas[(i+k)*2 + 1] = opa;
#endif
}
i += gif->width;
}
break;
case 3: /* Restore to previous, i.e., don't update canvas.*/
break;
default:
/* Add frame non-transparent pixels to canvas. */
render_frame_rect(gif, gif->canvas);
}
}
/* Return 1 if got a frame; 0 if got GIF trailer; -1 if error. */
int
gd_get_frame(gd_GIF *gif)
{
char sep;
dispose(gif);
f_gif_read(gif, &sep, 1);
while (sep != ',') {
if (sep == ';') {
f_gif_seek(gif, gif->anim_start, LV_FS_SEEK_SET);
if(gif->loop_count == 1 || gif->loop_count < 0) {
return 0;
}
else if(gif->loop_count > 1) {
gif->loop_count--;
}
}
else if (sep == '!')
read_ext(gif);
else return -1;
f_gif_read(gif, &sep, 1);
}
if (read_image(gif) == -1)
return -1;
return 1;
}
void
gd_render_frame(gd_GIF *gif, uint8_t *buffer)
{
// uint32_t i;
// uint32_t j;
// for(i = 0, j = 0; i < gif->width * gif->height * 3; i+= 3, j+=4) {
// buffer[j + 0] = gif->canvas[i + 2];
// buffer[j + 1] = gif->canvas[i + 1];
// buffer[j + 2] = gif->canvas[i + 0];
// buffer[j + 3] = 0xFF;
// }
// memcpy(buffer, gif->canvas, gif->width * gif->height * 3);
render_frame_rect(gif, buffer);
}
void
gd_rewind(gd_GIF *gif)
{
gif->loop_count = -1;
f_gif_seek(gif, gif->anim_start, LV_FS_SEEK_SET);
}
void
gd_close_gif(gd_GIF *gif)
{
f_gif_close(gif);
#if (GIF_MEM_FRAME==1)
memset(gif, 0, sizeof(gd_GIF));
#else
lv_mem_free(gif);
#endif
}
static bool f_gif_open(gd_GIF * gif, const void * path, bool is_file)
{
gif->f_rw_p = 0;
#if (GIF_EXTERN_FLASH_DEC==1)
gif->offset = 0;
#else
gif->data = NULL;
#endif
gif->is_file = is_file;
if(is_file) {
lv_fs_res_t res = lv_fs_open(&gif->fd, path, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) return false;
else return true;
} else {
#if (GIF_EXTERN_FLASH_DEC==1)
gif->offset = (uint32_t)path;
#else
gif->data = path;
#endif
return true;
}
}
static void f_gif_read(gd_GIF * gif, void * buf, size_t len)
{
if(gif->is_file) {
lv_fs_read(&gif->fd, buf, len, NULL);
} else
{
#if (GIF_EXTERN_FLASH_DEC==1)
extern void extern_flash_read(uint8_t *Buffer, uint32_t flash_Address, uint32_t Length);
extern_flash_read(buf,(gif->offset+gif->f_rw_p), len);
#else
memcpy(buf, &gif->data[gif->f_rw_p], len);
#endif
gif->f_rw_p += len;
}
}
static int f_gif_seek(gd_GIF * gif, size_t pos, int k)
{
if(gif->is_file) {
lv_fs_seek(&gif->fd, pos, k);
uint32_t x;
lv_fs_tell(&gif->fd, &x);
return x;
} else {
if(k == LV_FS_SEEK_CUR) gif->f_rw_p += pos;
else if(k == LV_FS_SEEK_SET) gif->f_rw_p = pos;
return gif->f_rw_p;
}
}
static void f_gif_close(gd_GIF * gif)
{
if(gif->is_file) {
lv_fs_close(&gif->fd);
}
}
#endif /*LV_USE_GIF*/

View File

@ -0,0 +1,66 @@
#ifndef GIFDEC_H
#define GIFDEC_H
#include <stdint.h>
#include "../../../misc/lv_fs.h"
#if LV_USE_GIF
#define GIF_EXTERN_FLASH_DEC 1
typedef struct gd_Palette {
int size;
uint8_t colors[0x100 * 3];
} gd_Palette;
typedef struct gd_GCE {
uint16_t delay;
uint8_t tindex;
uint8_t disposal;
int input;
int transparency;
} gd_GCE;
typedef struct gd_GIF {
lv_fs_file_t fd;
#if (GIF_EXTERN_FLASH_DEC==1)
uint32_t offset;
#else
const char * data;
#endif
uint8_t is_file;
uint32_t f_rw_p;
int32_t anim_start;
uint16_t width, height;
uint16_t depth;
int32_t loop_count;
gd_GCE gce;
gd_Palette *palette;
gd_Palette lct, gct;
void (*plain_text)(
struct gd_GIF *gif, uint16_t tx, uint16_t ty,
uint16_t tw, uint16_t th, uint8_t cw, uint8_t ch,
uint8_t fg, uint8_t bg
);
void (*comment)(struct gd_GIF *gif);
void (*application)(struct gd_GIF *gif, char id[8], char auth[3]);
uint16_t fx, fy, fw, fh;
uint8_t bgindex;
uint8_t *canvas, *frame;
} gd_GIF;
gd_GIF * gd_open_gif_file(const char *fname);
gd_GIF * gd_open_gif_data(const void *data);
gd_GIF *gd_open_gif_data_ex(const void *data);
void gd_render_frame(gd_GIF *gif, uint8_t *buffer);
int gd_get_frame(gd_GIF *gif);
void gd_rewind(gd_GIF *gif);
void gd_close_gif(gd_GIF *gif);
#endif /*LV_USE_GIF*/
#endif /* GIFDEC_H */

View File

@ -0,0 +1,159 @@
/**
* @file lv_gifenc.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_gif.h"
#if LV_USE_GIF
#include "gifdec.h"
/*********************
* DEFINES
*********************/
#define MY_CLASS &lv_gif_class
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_gif_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
static void lv_gif_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
static void next_frame_task_cb(lv_timer_t * t);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_gif_class = {
.constructor_cb = lv_gif_constructor,
.destructor_cb = lv_gif_destructor,
.instance_size = sizeof(lv_gif_t),
.base_class = &lv_img_class
};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_obj_t * lv_gif_create(lv_obj_t * parent)
{
LV_LOG_INFO("begin");
lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
lv_obj_class_init_obj(obj);
return obj;
}
void lv_gif_set_src(lv_obj_t * obj, const void * src)
{
lv_gif_t * gifobj = (lv_gif_t *) obj;
/*Close previous gif if any*/
if(gifobj->gif) {
lv_img_cache_invalidate_src(&gifobj->imgdsc);
gd_close_gif(gifobj->gif);
gifobj->gif = NULL;
gifobj->imgdsc.data = NULL;
}
#if (GIF_EXTERN_FLASH_DEC==1)
gifobj->gif = gd_open_gif_data_ex(src);
#else
if(lv_img_src_get_type(src) == LV_IMG_SRC_VARIABLE) {
const lv_img_dsc_t * img_dsc = src;
gifobj->gif = gd_open_gif_data(img_dsc->data);
}
else if(lv_img_src_get_type(src) == LV_IMG_SRC_FILE) {
gifobj->gif = gd_open_gif_file(src);
}
if(gifobj->gif == NULL) {
LV_LOG_WARN("Could't load the source");
return;
}
#endif
gifobj->imgdsc.data = gifobj->gif->canvas;
gifobj->imgdsc.header.always_zero = 0;
//gifobj->imgdsc.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
//gifobj->imgdsc.header.cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED;
gifobj->imgdsc.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
gifobj->imgdsc.header.h = gifobj->gif->height;
gifobj->imgdsc.header.w = gifobj->gif->width;
gifobj->imgdsc.header.reserved = 2;
gifobj->last_call = lv_tick_get();
lv_img_set_src(obj, &gifobj->imgdsc);
lv_timer_resume(gifobj->timer);
lv_timer_reset(gifobj->timer);
next_frame_task_cb(gifobj->timer);
}
void lv_gif_restart(lv_obj_t * obj)
{
lv_gif_t * gifobj = (lv_gif_t *) obj;
gd_rewind(gifobj->gif);
lv_timer_resume(gifobj->timer);
lv_timer_reset(gifobj->timer);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void lv_gif_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
{
LV_UNUSED(class_p);
lv_gif_t * gifobj = (lv_gif_t *) obj;
gifobj->gif = NULL;
gifobj->timer = lv_timer_create(next_frame_task_cb, 10, obj);
lv_timer_pause(gifobj->timer);
}
static void lv_gif_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
{
LV_UNUSED(class_p);
lv_gif_t * gifobj = (lv_gif_t *) obj;
lv_img_cache_invalidate_src(&gifobj->imgdsc);
if(gifobj->gif)
gd_close_gif(gifobj->gif);
lv_timer_del(gifobj->timer);
}
static void next_frame_task_cb(lv_timer_t * t)
{
lv_obj_t * obj = t->user_data;
lv_gif_t * gifobj = (lv_gif_t *) obj;
uint32_t elaps = lv_tick_elaps(gifobj->last_call);
if(elaps < gifobj->gif->gce.delay * 10) return;
gifobj->last_call = lv_tick_get();
int has_next = gd_get_frame(gifobj->gif);
if(has_next == 0) {
/*It was the last repeat*/
lv_res_t res = lv_event_send(obj, LV_EVENT_READY, NULL);
lv_timer_pause(t);
if(res != LV_FS_RES_OK) return;
}
gd_render_frame(gifobj->gif, (uint8_t *)gifobj->imgdsc.data);
lv_img_cache_invalidate_src(lv_img_get_src(obj));
lv_obj_invalidate(obj);
}
#endif /*LV_USE_GIF*/

View File

@ -0,0 +1,58 @@
/**
* @file lv_gif.h
*
*/
#ifndef LV_GIF_H
#define LV_GIF_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_GIF
#include "gifdec.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_img_t img;
gd_GIF * gif;
lv_timer_t * timer;
lv_img_dsc_t imgdsc;
uint32_t last_call;
} lv_gif_t;
extern const lv_obj_class_t lv_gif_class;
/**********************
* GLOBAL PROTOTYPES
**********************/
lv_obj_t * lv_gif_create(lv_obj_t * parent);
void lv_gif_set_src(lv_obj_t * obj, const void * src);
void lv_gif_restart(lv_obj_t * gif);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GIF*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_GIF_H*/

View File

@ -0,0 +1,46 @@
/**
* @file lv_libs.h
*
*/
#ifndef LV_LIBS_H
#define LV_LIBS_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "bmp/lv_bmp.h"
#include "fsdrv/lv_fsdrv.h"
#include "png/lv_png.h"
#include "gif/lv_gif.h"
#include "qrcode/lv_qrcode.h"
#include "sjpg/lv_sjpg.h"
#include "freetype/lv_freetype.h"
#include "rlottie/lv_rlottie.h"
#include "ffmpeg/lv_ffmpeg.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_LIBS_H*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,258 @@
/**
* @file lv_png.c
*
*/
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_PNG
#include "lv_png.h"
#include "lodepng.h"
#include <stdlib.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static lv_res_t decoder_info(struct _lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header);
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 VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Register the PNG decoder functions in LVGL
*/
void lv_png_init(void)
{
lv_img_decoder_t * dec = lv_img_decoder_create();
lv_img_decoder_set_info_cb(dec, decoder_info);
lv_img_decoder_set_open_cb(dec, decoder_open);
lv_img_decoder_set_close_cb(dec, decoder_close);
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Get info about a PNG image
* @param src can be file name or pointer to a C array
* @param header store the info here
* @return LV_RES_OK: no error; LV_RES_INV: can't get the info
*/
static lv_res_t decoder_info(struct _lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header)
{
(void) decoder; /*Unused*/
lv_img_src_t src_type = lv_img_src_get_type(src); /*Get the source type*/
/*If it's a PNG file...*/
if(src_type == LV_IMG_SRC_FILE) {
const char * fn = src;
if(strcmp(lv_fs_get_ext(fn), "png") == 0) { /*Check the extension*/
/* Read the width and height from the file. They have a constant location:
* [16..23]: width
* [24..27]: height
*/
uint32_t size[2];
lv_fs_file_t f;
lv_fs_res_t res = lv_fs_open(&f, fn, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) return LV_RES_INV;
lv_fs_seek(&f, 16, LV_FS_SEEK_SET);
uint32_t rn;
lv_fs_read(&f, &size, 8, &rn);
lv_fs_close(&f);
if(rn != 8) return LV_RES_INV;
/*Save the data in the header*/
header->always_zero = 0;
header->cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
/*The width and height are stored in Big endian format so convert them to little endian*/
header->w = (lv_coord_t)((size[0] & 0xff000000) >> 24) + ((size[0] & 0x00ff0000) >> 8);
header->h = (lv_coord_t)((size[1] & 0xff000000) >> 24) + ((size[1] & 0x00ff0000) >> 8);
return LV_RES_OK;
}
}
/*If it's a PNG file in a C array...*/
else if(src_type == LV_IMG_SRC_VARIABLE) {
const lv_img_dsc_t * img_dsc = src;
const uint32_t data_size = img_dsc->data_size;
const uint8_t magic[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
if(data_size < sizeof(magic)) return LV_RES_INV;
if(memcmp(magic, img_dsc->data, sizeof(magic))) return LV_RES_INV;
header->always_zero = 0;
header->cf = img_dsc->header.cf; /*Save the color format*/
header->w = img_dsc->header.w; /*Save the color width*/
header->h = img_dsc->header.h; /*Save the color height*/
return LV_RES_OK;
}
return LV_RES_INV; /*If didn't succeeded earlier then it's an error*/
}
/**
* Open a PNG image and return the decided image
* @param src can be file name or pointer to a C array
* @param style style of the image object (unused now but certain formats might use it)
* @return pointer to the decoded image or `LV_IMG_DECODER_OPEN_FAIL` if failed
*/
static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
{
(void) decoder; /*Unused*/
uint32_t error; /*For the return values of PNG decoder functions*/
uint8_t * img_data = NULL;
/*If it's a PNG file...*/
if(dsc->src_type == LV_IMG_SRC_FILE) {
const char * fn = dsc->src;
if(strcmp(lv_fs_get_ext(fn), "png") == 0) { /*Check the extension*/
/*Load the PNG file into buffer. It's still compressed (not decoded)*/
unsigned char * png_data; /*Pointer to the loaded data. Same as the original file just loaded into the RAM*/
size_t png_data_size; /*Size of `png_data` in bytes*/
error = lodepng_load_file(&png_data, &png_data_size, fn); /*Load the file*/
if(error) {
LV_LOG_WARN("error %u: %s\n", error, lodepng_error_text(error));
return LV_RES_INV;
}
/*Decode the PNG image*/
uint32_t png_width; /*Will be the width of the decoded image*/
uint32_t png_height; /*Will be the width of the decoded image*/
/*Decode the loaded image in ARGB8888 */
error = lodepng_decode32(&img_data, &png_width, &png_height, png_data, png_data_size);
lv_mem_free(png_data); /*Free the loaded file*/
if(error) {
if(img_data != NULL) {
lv_mem_free(img_data);
}
LV_LOG_WARN("error %u: %s\n", error, lodepng_error_text(error));
return LV_RES_INV;
}
/*Convert the image to the system's color depth*/
convert_color_depth(img_data, png_width * png_height);
dsc->img_data = img_data;
return LV_RES_OK; /*The image is fully decoded. Return with its pointer*/
}
}
/*If it's a PNG file in a C array...*/
else if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
const lv_img_dsc_t * img_dsc = dsc->src;
uint32_t png_width; /*No used, just required by he decoder*/
uint32_t png_height; /*No used, just required by he decoder*/
/*Decode the image in ARGB8888 */
error = lodepng_decode32(&img_data, &png_width, &png_height, img_dsc->data, img_dsc->data_size);
if(error) {
if(img_data != NULL) {
lv_mem_free(img_data);
}
return LV_RES_INV;
}
/*Convert the image to the system's color depth*/
convert_color_depth(img_data, png_width * png_height);
dsc->img_data = img_data;
return LV_RES_OK; /*Return with its pointer*/
}
return LV_RES_INV; /*If not returned earlier then it failed*/
}
/**
* Free the allocated resources
*/
static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
{
LV_UNUSED(decoder); /*Unused*/
if(dsc->img_data) {
lv_mem_free((uint8_t *)dsc->img_data);
dsc->img_data = NULL;
}
}
/**
* If the display is not in 32 bit format (ARGB888) then covert the image to the current color depth
* @param img the ARGB888 image
* @param px_cnt number of pixels in `img`
*/
static void convert_color_depth(uint8_t * img, uint32_t px_cnt)
{
#if LV_COLOR_DEPTH == 32
lv_color32_t * img_argb = (lv_color32_t *)img;
lv_color_t c;
lv_color_t * img_c = (lv_color_t *) img;
uint32_t i;
for(i = 0; i < px_cnt; i++) {
c = lv_color_make(img_argb[i].ch.red, img_argb[i].ch.green, img_argb[i].ch.blue);
img_c[i].ch.red = c.ch.blue;
img_c[i].ch.blue = c.ch.red;
}
#elif LV_COLOR_DEPTH == 16
lv_color32_t * img_argb = (lv_color32_t *)img;
lv_color_t c;
uint32_t i;
for(i = 0; i < px_cnt; i++) {
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;
}
#elif LV_COLOR_DEPTH == 8
lv_color32_t * img_argb = (lv_color32_t *)img;
lv_color_t c;
uint32_t i;
for(i = 0; i < px_cnt; i++) {
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;
}
#elif LV_COLOR_DEPTH == 1
lv_color32_t * img_argb = (lv_color32_t *)img;
uint8_t b;
uint32_t i;
for(i = 0; i < px_cnt; i++) {
b = 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] = b > 128 ? 1 : 0;
}
#endif
}
#endif /*LV_USE_PNG*/

View File

@ -0,0 +1,46 @@
/**
* @file lv_png.h
*
*/
#ifndef LV_PNG_H
#define LV_PNG_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_PNG
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Register the PNG decoder functions in LVGL
*/
void lv_png_init(void);
/**********************
* MACROS
**********************/
#endif /*LV_USE_PNG*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_PNG_H*/

View File

@ -0,0 +1,215 @@
/**
* @file lv_qrcode.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_qrcode.h"
#if LV_USE_QRCODE
#include "qrcodegen.h"
/*********************
* DEFINES
*********************/
#define MY_CLASS &lv_qrcode_class
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_qrcode_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
static void lv_qrcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_qrcode_class = {
.constructor_cb = lv_qrcode_constructor,
.destructor_cb = lv_qrcode_destructor,
.base_class = &lv_canvas_class
};
static lv_coord_t size_param;
static lv_color_t dark_color_param;
static lv_color_t light_color_param;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Create an empty QR code (an `lv_canvas`) object.
* @param parent point to an object where to create the QR code
* @param size width and height of the QR code
* @param dark_color dark color of the QR code
* @param light_color light color of the QR code
* @return pointer to the created QR code object
*/
lv_obj_t * lv_qrcode_create(lv_obj_t * parent, lv_coord_t size, lv_color_t dark_color, lv_color_t light_color)
{
LV_LOG_INFO("begin");
size_param = size;
light_color_param = light_color;
dark_color_param = dark_color;
lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
lv_obj_class_init_obj(obj);
return obj;
}
/**
* Set the data of a QR code object
* @param qrcode pointer to aQ code object
* @param data data to display
* @param data_len length of data in bytes
* @return LV_RES_OK: if no error; LV_RES_INV: on error
*/
lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_len)
{
lv_color_t c;
c.full = 1;
lv_canvas_fill_bg(qrcode, c, LV_OPA_COVER);
if(data_len > qrcodegen_BUFFER_LEN_MAX) return LV_RES_INV;
lv_img_dsc_t * imgdsc = lv_canvas_get_img(qrcode);
int32_t qr_version = qrcodegen_getMinFitVersion(qrcodegen_Ecc_MEDIUM, data_len);
if(qr_version <= 0) return LV_RES_INV;
int32_t qr_size = qrcodegen_version2size(qr_version);
if(qr_size <= 0) return LV_RES_INV;
int32_t scale = imgdsc->header.w / qr_size;
if(scale <= 0) return LV_RES_INV;
int32_t remain = imgdsc->header.w % qr_size;
/* The qr version is incremented by four point */
uint32_t version_extend = remain / (scale << 2);
if(version_extend && qr_version < qrcodegen_VERSION_MAX) {
qr_version = qr_version + version_extend > qrcodegen_VERSION_MAX ?
qrcodegen_VERSION_MAX : qr_version + version_extend;
}
uint8_t * qr0 = lv_mem_alloc(qrcodegen_BUFFER_LEN_FOR_VERSION(qr_version));
LV_ASSERT_MALLOC(qr0);
uint8_t * data_tmp = lv_mem_alloc(qrcodegen_BUFFER_LEN_FOR_VERSION(qr_version));
LV_ASSERT_MALLOC(data_tmp);
lv_memcpy(data_tmp, data, data_len);
bool ok = qrcodegen_encodeBinary(data_tmp, data_len,
qr0, qrcodegen_Ecc_MEDIUM,
qr_version, qr_version,
qrcodegen_Mask_AUTO, true);
if(!ok) {
lv_mem_free(qr0);
lv_mem_free(data_tmp);
return LV_RES_INV;
}
lv_coord_t obj_w = imgdsc->header.w;
qr_size = qrcodegen_getSize(qr0);
scale = obj_w / qr_size;
int scaled = qr_size * scale;
int margin = (obj_w - scaled) / 2;
uint8_t * buf_u8 = (uint8_t *)imgdsc->data + 8; /*+8 skip the palette*/
/* Copy the qr code canvas:
* A simple `lv_canvas_set_px` would work but it's slow for so many pixels.
* So buffer 1 byte (8 px) from the qr code and set it in the canvas image */
uint32_t row_byte_cnt = (imgdsc->header.w + 7) >> 3;
int y;
for(y = margin; y < scaled + margin; y += scale) {
uint8_t b = 0;
uint8_t p = 0;
bool aligned = false;
int x;
for(x = margin; x < scaled + margin; x++) {
bool a = qrcodegen_getModule(qr0, (x - margin) / scale, (y - margin) / scale);
if(aligned == false && (x & 0x7) == 0) aligned = true;
if(aligned == false) {
c.full = a ? 0 : 1;
lv_canvas_set_px_color(qrcode, x, y, c);
}
else {
if(!a) b |= (1 << (7 - p));
p++;
if(p == 8) {
uint32_t px = row_byte_cnt * y + (x >> 3);
buf_u8[px] = b;
b = 0;
p = 0;
}
}
}
/*Process the last byte of the row*/
if(p) {
/*Make the rest of the bits white*/
b |= (1 << (8 - p)) - 1;
uint32_t px = row_byte_cnt * y + (x >> 3);
buf_u8[px] = b;
}
/*The Qr is probably scaled so simply to the repeated rows*/
int s;
const uint8_t * row_ori = buf_u8 + row_byte_cnt * y;
for(s = 1; s < scale; s++) {
lv_memcpy((uint8_t *)buf_u8 + row_byte_cnt * (y + s), row_ori, row_byte_cnt);
}
}
lv_mem_free(qr0);
lv_mem_free(data_tmp);
return LV_RES_OK;
}
void lv_qrcode_delete(lv_obj_t * qrcode)
{
lv_obj_del(qrcode);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void lv_qrcode_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
{
LV_UNUSED(class_p);
uint32_t buf_size = LV_CANVAS_BUF_SIZE_INDEXED_1BIT(size_param, size_param);
uint8_t * buf = lv_mem_alloc(buf_size);
LV_ASSERT_MALLOC(buf);
if(buf == NULL) return;
lv_canvas_set_buffer(obj, buf, size_param, size_param, LV_IMG_CF_INDEXED_1BIT);
lv_canvas_set_palette(obj, 0, dark_color_param);
lv_canvas_set_palette(obj, 1, light_color_param);
}
static void lv_qrcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
{
LV_UNUSED(class_p);
lv_img_dsc_t * img = lv_canvas_get_img(obj);
lv_img_cache_invalidate_src(img);
lv_mem_free((void *)img->data);
img->data = NULL;
}
#endif /*LV_USE_QRCODE*/

Some files were not shown because too many files have changed in this diff Show More