2016-06-08 07:25:08 +02:00
/**
* @ file lv_img . c
*
*/
/*********************
* INCLUDES
* * * * * * * * * * * * * * * * * * * * */
2017-11-26 23:57:39 +01:00
# include "../../lv_conf.h"
2017-11-26 11:38:28 +01:00
# if USE_LV_IMG != 0
2016-06-08 07:25:08 +02:00
2018-01-19 15:40:22 +01:00
/*Testing of dependencies*/
# if USE_LV_LABEL == 0
# error "lv_img: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) "
# endif
2016-06-08 07:25:08 +02:00
# include "lv_img.h"
2017-11-16 15:32:33 +01:00
# include "../lv_themes/lv_theme.h"
2017-11-23 20:42:14 +01:00
# include "../lv_misc/lv_fs.h"
# include "../lv_misc/lv_ufs.h"
2017-11-26 11:38:28 +01:00
# include "../lv_misc/lv_txt.h"
2017-01-16 12:30:22 +01:00
2016-06-08 07:25:08 +02:00
/*********************
* DEFINES
* * * * * * * * * * * * * * * * * * * * */
/**********************
* TYPEDEFS
* * * * * * * * * * * * * * * * * * * * * */
/**********************
* STATIC PROTOTYPES
* * * * * * * * * * * * * * * * * * * * * */
2017-11-23 21:28:36 +01:00
static bool lv_img_design ( lv_obj_t * img , const lv_area_t * mask , lv_design_mode_t mode ) ;
2017-11-13 16:11:05 +01:00
static lv_res_t lv_img_signal ( lv_obj_t * img , lv_signal_t sign , void * param ) ;
2017-01-16 12:30:22 +01:00
2016-06-08 07:25:08 +02:00
/**********************
* STATIC VARIABLES
* * * * * * * * * * * * * * * * * * * * * */
2017-11-13 16:11:05 +01:00
static lv_signal_func_t ancestor_signal ;
2016-06-08 07:25:08 +02:00
/**********************
* MACROS
* * * * * * * * * * * * * * * * * * * * * */
/**********************
* GLOBAL FUNCTIONS
* * * * * * * * * * * * * * * * * * * * * */
/**
* Create an image objects
2016-10-07 11:15:46 +02:00
* @ param par pointer to an object , it will be the parent of the new button
2017-04-13 16:12:03 +02:00
* @ param copy pointer to a image object , if not NULL then the new object will be copied from it
2016-06-08 07:25:08 +02:00
* @ return pointer to the created image
*/
2016-10-07 11:15:46 +02:00
lv_obj_t * lv_img_create ( lv_obj_t * par , lv_obj_t * copy )
2016-06-08 07:25:08 +02:00
{
2016-10-07 11:15:46 +02:00
lv_obj_t * new_img = NULL ;
2016-06-08 07:25:08 +02:00
/*Create a basic object*/
2016-10-07 17:33:35 +02:00
new_img = lv_obj_create ( par , copy ) ;
2017-11-26 11:38:28 +01:00
lv_mem_assert ( new_img ) ;
2017-11-13 16:11:05 +01:00
if ( ancestor_signal = = NULL ) ancestor_signal = lv_obj_get_signal_func ( new_img ) ;
2016-06-08 07:25:08 +02:00
/*Extend the basic object to image object*/
2017-10-20 10:17:02 +02:00
lv_img_ext_t * ext = lv_obj_allocate_ext_attr ( new_img , sizeof ( lv_img_ext_t ) ) ;
2017-11-26 11:38:28 +01:00
lv_mem_assert ( ext ) ;
2018-02-23 13:56:04 +01:00
ext - > src = NULL ;
ext - > src_type = LV_IMG_SRC_UNKNOWN ;
2017-01-02 14:10:32 +01:00
ext - > w = lv_obj_get_width ( new_img ) ;
ext - > h = lv_obj_get_height ( new_img ) ;
2018-02-23 13:56:04 +01:00
ext - > chroma_keyed = 0 ;
ext - > alpha_byte = 0 ;
2017-04-28 16:12:35 +02:00
ext - > auto_size = 1 ;
2016-06-08 07:25:08 +02:00
/*Init the new object*/
2017-10-20 10:17:02 +02:00
lv_obj_set_signal_func ( new_img , lv_img_signal ) ;
lv_obj_set_design_func ( new_img , lv_img_design ) ;
2016-06-08 07:25:08 +02:00
2016-10-07 11:15:46 +02:00
if ( copy = = NULL ) {
2017-01-02 14:10:32 +01:00
/* Enable auto size for non screens
* because image screens are wallpapers
* and must be screen sized */
if ( par ! = NULL ) ext - > auto_size = 1 ;
else ext - > auto_size = 0 ;
2017-11-16 15:32:33 +01:00
if ( par ! = NULL ) lv_obj_set_style ( new_img , NULL ) ; /*Inherit the style by default*/
else lv_obj_set_style ( new_img , & lv_style_plain ) ; /*Set a style for screens*/
2016-06-08 07:25:08 +02:00
} else {
2017-10-20 10:17:02 +02:00
lv_img_ext_t * copy_ext = lv_obj_get_ext_attr ( copy ) ;
2017-04-21 09:15:39 +02:00
ext - > auto_size = copy_ext - > auto_size ;
2018-02-23 13:56:04 +01:00
lv_img_set_src ( new_img , copy_ext - > src ) ;
2017-01-02 14:10:32 +01:00
2017-01-08 13:06:41 +01:00
/*Refresh the style with new signal function*/
2017-10-20 10:17:02 +02:00
lv_obj_refresh_style ( new_img ) ;
2016-06-08 07:25:08 +02:00
}
2016-10-07 11:15:46 +02:00
return new_img ;
2016-06-08 07:25:08 +02:00
}
/*=====================
* Setter functions
* = = = = = = = = = = = = = = = = = = = = */
2018-02-09 12:40:00 +01:00
/**
* Set the pixel map to display by the image
* @ param img pointer to an image object
* @ param data the image data
*/
2018-02-23 13:56:04 +01:00
void lv_img_set_src ( lv_obj_t * img , const void * src_img )
2018-02-09 12:40:00 +01:00
{
2018-02-23 13:56:04 +01:00
lv_img_src_t src_type = lv_img_get_src_type ( src_img ) ;
2018-02-09 12:40:00 +01:00
lv_img_ext_t * ext = lv_obj_get_ext_attr ( img ) ;
2018-03-04 17:03:37 +01:00
# if USE_LV_FILESYSTEM == 0
if ( src_type = = LV_IMG_SRC_FILE ) src_type = LV_IMG_SRC_UNKNOWN ;
# endif
2018-02-23 13:56:04 +01:00
if ( src_type = = LV_IMG_SRC_UNKNOWN ) {
if ( ext - > src_type = = LV_IMG_SRC_SYMBOL | | ext - > src_type = = LV_IMG_SRC_FILE ) {
lv_mem_free ( ext - > src ) ;
}
ext - > src = NULL ;
ext - > src_type = LV_IMG_SRC_UNKNOWN ;
return ;
}
2018-02-09 12:40:00 +01:00
2018-02-23 13:56:04 +01:00
ext - > src_type = src_type ;
if ( src_type = = LV_IMG_SRC_VARIABLE ) {
ext - > src = src_img ;
ext - > w = ( ( lv_img_t * ) src_img ) - > header . w ;
ext - > h = ( ( lv_img_t * ) src_img ) - > header . h ;
ext - > chroma_keyed = ( ( lv_img_t * ) src_img ) - > header . chroma_keyed ;
ext - > alpha_byte = ( ( lv_img_t * ) src_img ) - > header . alpha_byte ;
lv_obj_set_size ( img , ext - > w , ext - > h ) ;
}
2018-03-04 17:03:37 +01:00
# if USE_LV_FILESYSTEM
2018-02-23 13:56:04 +01:00
else if ( src_type = = LV_IMG_SRC_FILE ) {
2017-11-24 17:48:47 +01:00
lv_fs_file_t file ;
lv_fs_res_t res ;
2018-02-23 13:56:04 +01:00
lv_img_t img_file_data ;
2017-01-16 12:30:22 +01:00
uint32_t rn ;
2018-02-23 13:56:04 +01:00
res = lv_fs_open ( & file , src_img , LV_FS_MODE_RD ) ;
2017-12-03 22:32:09 +01:00
if ( res = = LV_FS_RES_OK ) {
2018-02-23 13:56:04 +01:00
res = lv_fs_read ( & file , & img_file_data , sizeof ( img_file_data ) , & rn ) ;
2017-01-16 12:30:22 +01:00
}
2016-06-08 07:25:08 +02:00
2017-01-16 12:30:22 +01:00
/*Create a dummy header on fs error*/
2018-02-23 13:56:04 +01:00
if ( res ! = LV_FS_RES_OK | | rn ! = sizeof ( img_file_data ) ) {
img_file_data . header . w = lv_obj_get_width ( img ) ;
img_file_data . header . h = lv_obj_get_height ( img ) ;
img_file_data . header . chroma_keyed = 0 ;
img_file_data . header . alpha_byte = 0 ;
2017-01-16 12:30:22 +01:00
}
2016-06-08 07:25:08 +02:00
2017-11-24 17:48:47 +01:00
lv_fs_close ( & file ) ;
2016-06-08 07:25:08 +02:00
2018-02-23 13:56:04 +01:00
ext - > w = img_file_data . header . w ;
ext - > h = img_file_data . header . h ;
ext - > chroma_keyed = img_file_data . header . chroma_keyed ;
ext - > alpha_byte = img_file_data . header . alpha_byte ;
/* If the new and the old src are the same then it was only a refresh.*/
if ( ext - > src ! = src_img ) {
lv_mem_free ( ext - > src ) ;
char * new_fn = lv_mem_alloc ( strlen ( src_img ) + 1 ) ;
strcpy ( new_fn , src_img ) ;
ext - > src = new_fn ;
}
}
2018-03-04 17:03:37 +01:00
# endif
2018-02-23 13:56:04 +01:00
else if ( src_type = = LV_IMG_SRC_SYMBOL ) {
2017-04-13 10:20:35 +02:00
lv_style_t * style = lv_obj_get_style ( img ) ;
2017-11-23 21:28:36 +01:00
lv_point_t size ;
2018-02-23 13:56:04 +01:00
lv_txt_get_size ( & size , src_img , style - > text . font , style - > text . letter_space , style - > text . line_space , LV_COORD_MAX , LV_TXT_FLAG_NONE ) ;
2017-01-16 12:30:22 +01:00
ext - > w = size . x ;
ext - > h = size . y ;
2018-02-23 13:56:04 +01:00
ext - > chroma_keyed = 1 ; /*Symbols always have transparent parts, Important because of cover check in the design function*/
/* If the new and the old src are the same then it was only a refresh.*/
if ( ext - > src ! = src_img ) {
lv_mem_free ( ext - > src ) ;
char * new_txt = lv_mem_alloc ( strlen ( src_img ) + 1 ) ;
strcpy ( new_txt , src_img ) ;
ext - > src = new_txt ;
}
}
2017-01-16 12:30:22 +01:00
2016-10-07 11:15:46 +02:00
if ( lv_img_get_auto_size ( img ) ! = false ) {
2017-01-16 12:30:22 +01:00
lv_obj_set_size ( img , ext - > w , ext - > h ) ;
2016-06-08 07:25:08 +02:00
}
2016-12-15 19:47:27 +01:00
2017-10-20 10:17:02 +02:00
lv_obj_invalidate ( img ) ;
2016-06-08 07:25:08 +02:00
}
/**
2016-10-07 11:15:46 +02:00
* Enable the auto size feature .
* If enabled the object size will be same as the picture size .
* @ param img pointer to an image
2017-11-13 16:11:05 +01:00
* @ param autosize_en true : auto size enable , false : auto size disable
2017-01-09 08:50:38 +01:00
*/
2017-11-13 16:11:05 +01:00
void lv_img_set_auto_size ( lv_obj_t * img , bool autosize_en )
2017-01-09 08:50:38 +01:00
{
2017-10-20 10:17:02 +02:00
lv_img_ext_t * ext = lv_obj_get_ext_attr ( img ) ;
2017-01-09 08:50:38 +01:00
2017-11-13 16:11:05 +01:00
ext - > auto_size = ( autosize_en = = false ? 0 : 1 ) ;
2017-01-09 08:50:38 +01:00
}
2016-06-08 07:25:08 +02:00
/*=====================
* Getter functions
* = = = = = = = = = = = = = = = = = = = = */
2018-02-23 17:03:00 +01:00
/**
* 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 an file ( e . g . " S:/folder/image.bin " )
* - or a symbol ( e . g . SYMBOL_CLOSE )
* @ return type of the image source LV_IMG_SRC_VARIABLE / FILE / SYMBOL / UNKOWN
*/
2018-02-23 13:56:04 +01:00
lv_img_src_t lv_img_get_src_type ( const void * src )
{
if ( src = = NULL ) return LV_IMG_SRC_UNKNOWN ;
const uint8_t * u8_p = src ;
/*The first byte shows the type of the image source*/
if ( u8_p [ 0 ] > = ' A ' & & u8_p [ 0 ] < = ' Z ' ) return LV_IMG_SRC_FILE ; /*It's a driver letter*/
2018-02-23 15:22:23 +01:00
else if ( ( ( u8_p [ 0 ] & 0xFC ) > > 2 ) = = LV_IMG_FORMAT_INTERNAL_RAW ) return LV_IMG_SRC_VARIABLE ; /*Mask the file format part og of lv_img_t header. IT should be 0 which means C array */
2018-02-24 11:55:39 +01:00
else if ( u8_p [ 0 ] > = ' ' ) return LV_IMG_SRC_SYMBOL ; /*Other printable characters are considered symbols*/
2018-02-23 13:56:04 +01:00
else return LV_IMG_SRC_UNKNOWN ;
}
2017-10-31 16:25:52 +01:00
/**
* Get the name of the file set for an image
* @ param img pointer to an image
* @ return file name
*/
const char * lv_img_get_file_name ( lv_obj_t * img )
{
lv_img_ext_t * ext = lv_obj_get_ext_attr ( img ) ;
2018-02-23 17:03:00 +01:00
if ( ext - > src_type = = LV_IMG_SRC_FILE ) return ext - > src ;
else return " " ;
2017-10-31 16:25:52 +01:00
}
2016-06-08 07:25:08 +02:00
/**
* Get the auto size enable attribute
2016-10-07 11:15:46 +02:00
* @ param img pointer to an image
2016-06-08 07:25:08 +02:00
* @ return true : auto size is enabled , false : auto size is disabled
*/
2016-10-07 11:15:46 +02:00
bool lv_img_get_auto_size ( lv_obj_t * img )
2016-06-08 07:25:08 +02:00
{
2017-10-20 10:17:02 +02:00
lv_img_ext_t * ext = lv_obj_get_ext_attr ( img ) ;
2016-06-08 07:25:08 +02:00
2016-10-07 11:15:46 +02:00
return ext - > auto_size = = 0 ? false : true ;
2016-06-08 07:25:08 +02:00
}
/**********************
* STATIC FUNCTIONS
* * * * * * * * * * * * * * * * * * * * * */
/**
* Handle the drawing related tasks of the images
2016-10-07 11:15:46 +02:00
* @ param img pointer to an object
2016-06-08 07:25:08 +02:00
* @ param mask the object will be drawn only in this area
* @ param mode LV_DESIGN_COVER_CHK : only check if the object fully covers the ' mask_p ' area
* ( return ' true ' if yes )
* LV_DESIGN_DRAW : draw the object ( always return ' true ' )
2016-10-04 09:45:39 +02:00
* LV_DESIGN_DRAW_POST : drawing after every children are drawn
2016-06-08 07:25:08 +02:00
* @ param return true / false , depends on ' mode '
*/
2017-11-23 21:28:36 +01:00
static bool lv_img_design ( lv_obj_t * img , const lv_area_t * mask , lv_design_mode_t mode )
2016-06-08 07:25:08 +02:00
{
2017-04-13 10:20:35 +02:00
lv_style_t * style = lv_obj_get_style ( img ) ;
2017-10-20 10:17:02 +02:00
lv_img_ext_t * ext = lv_obj_get_ext_attr ( img ) ;
2016-06-15 16:09:24 +02:00
2016-06-08 07:25:08 +02:00
if ( mode = = LV_DESIGN_COVER_CHK ) {
2017-04-21 17:11:47 +02:00
bool cover = false ;
2018-02-23 13:56:04 +01:00
if ( ext - > src_type = = LV_IMG_SRC_UNKNOWN | | ext - > src_type = = LV_IMG_SRC_SYMBOL ) return false ;
if ( ext - > chroma_keyed = = 0 & & ext - > alpha_byte = = 0 ) cover = lv_area_is_in ( mask , & img - > coords ) ;
2017-04-21 17:11:47 +02:00
return cover ;
2016-10-04 09:45:39 +02:00
} else if ( mode = = LV_DESIGN_DRAW_MAIN ) {
2017-01-10 08:36:12 +01:00
if ( ext - > h = = 0 | | ext - > w = = 0 ) return true ;
2018-02-23 13:56:04 +01:00
lv_area_t coords ;
2018-06-14 13:08:19 +02:00
lv_opa_t opa_scale = lv_obj_get_opa_scale ( img ) ;
2018-02-23 13:56:04 +01:00
lv_obj_get_coords ( img , & coords ) ;
if ( ext - > src_type = = LV_IMG_SRC_FILE | | ext - > src_type = = LV_IMG_SRC_VARIABLE ) {
lv_area_t cords_tmp ;
cords_tmp . y1 = coords . y1 ;
cords_tmp . y2 = coords . y1 + ext - > h - 1 ;
2016-10-04 09:45:39 +02:00
2018-02-23 13:56:04 +01:00
for ( ; cords_tmp . y1 < coords . y2 ; cords_tmp . y1 + = ext - > h , cords_tmp . y2 + = ext - > h ) {
cords_tmp . x1 = coords . x1 ;
cords_tmp . x2 = coords . x1 + ext - > w - 1 ;
for ( ; cords_tmp . x1 < coords . x2 ; cords_tmp . x1 + = ext - > w , cords_tmp . x2 + = ext - > w ) {
2018-06-14 13:08:19 +02:00
lv_draw_img ( & cords_tmp , mask , ext - > src , style , opa_scale ) ;
2018-02-23 13:56:04 +01:00
}
}
} else if ( ext - > src_type = = LV_IMG_SRC_SYMBOL ) {
2018-06-14 13:08:19 +02:00
lv_draw_label ( & coords , mask , style , opa_scale , ext - > src , LV_TXT_FLAG_NONE , NULL ) ;
2016-10-04 09:45:39 +02:00
2018-02-23 13:56:04 +01:00
} else {
2016-10-04 09:45:39 +02:00
2018-02-23 13:56:04 +01:00
/*Trigger the error handler of image drawer*/
2018-06-14 13:08:19 +02:00
lv_draw_img ( & img - > coords , mask , NULL , style , opa_scale ) ;
2017-10-31 16:25:52 +01:00
2016-10-04 09:45:39 +02:00
}
2016-06-08 07:25:08 +02:00
}
return true ;
}
2017-01-16 12:30:22 +01:00
2017-11-13 16:11:05 +01:00
/**
* Signal function of the image
2018-03-01 12:21:49 +01:00
* @ param img pointer to an image object
2017-11-13 16:11:05 +01:00
* @ param sign a signal type from lv_signal_t enum
* @ param param pointer to a signal specific variable
* @ return LV_RES_OK : the object is not deleted in the function ; LV_RES_INV : the object is deleted
*/
static lv_res_t lv_img_signal ( lv_obj_t * img , lv_signal_t sign , void * param )
{
lv_res_t res ;
/* Include the ancient signal function */
res = ancestor_signal ( img , sign , param ) ;
if ( res ! = LV_RES_OK ) return res ;
lv_img_ext_t * ext = lv_obj_get_ext_attr ( img ) ;
if ( sign = = LV_SIGNAL_CLEANUP ) {
2018-02-23 13:56:04 +01:00
if ( ext - > src_type = = LV_IMG_SRC_FILE | | ext - > src_type = = LV_IMG_SRC_SYMBOL ) {
lv_mem_free ( ext - > src ) ;
ext - > src = NULL ;
ext - > src_type = LV_IMG_SRC_UNKNOWN ;
}
2017-11-13 16:11:05 +01:00
}
else if ( sign = = LV_SIGNAL_STYLE_CHG ) {
/*Refresh the file name to refresh the symbol text size*/
2018-02-23 13:56:04 +01:00
if ( ext - > src_type = = LV_IMG_SRC_SYMBOL ) {
lv_img_set_src ( img , ext - > src ) ;
2017-11-13 16:11:05 +01:00
}
}
2018-02-28 15:37:41 +01:00
else if ( sign = = LV_SIGNAL_GET_TYPE ) {
lv_obj_type_t * buf = param ;
uint8_t i ;
for ( i = 0 ; i < LV_MAX_ANCESTOR_NUM - 1 ; i + + ) { /*Find the last set data*/
if ( buf - > type [ i ] = = NULL ) break ;
}
buf - > type [ i ] = " lv_img " ;
}
2017-11-13 16:11:05 +01:00
2017-11-15 15:50:33 +01:00
return res ;
2017-11-13 16:11:05 +01:00
}
2016-06-08 07:25:08 +02:00
# endif