mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
feat(img) add img_size property (#2284)
* Fix image zooming causes unexpected object size. Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com> * fix(img) invalidate size and layout on zoom and angle change * fix(img) not self-repeating under some zoom level. * minor fixes and refactoring * docs(img) add img_size Co-authored-by: Xu Xingliang <xuxingliang@xiaomi.com> Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
parent
33ba7225f5
commit
fe461caf7e
@ -90,7 +90,17 @@ The quality of the transformation can be adjusted with `lv_img_set_antialias(img
|
||||
The transformations require the whole image to be available. Therefore indexed images (`LV_IMG_CF_INDEXED_...`), alpha only images (`LV_IMG_CF_ALPHA_...`) or images from files can not be transformed.
|
||||
In other words transformations work only on true color images stored as C array, or if a custom [Image decoder](/overview/images#image-edecoder) returns the whole image.
|
||||
|
||||
Note that the real coordinates of image objects won't change during transformation. That is `lv_obj_get_width/height/x/y()` will return the original, non-zoomed coordinates.
|
||||
Note that the real coordinates of image objects won't change during transformation. That is `lv_obj_get_width/height/x/y()` will return the original, non-zoomed coordinates.
|
||||
|
||||
### Size mode
|
||||
|
||||
By default if the image is zoom or rotated the real coordinates of the image object are not changed.
|
||||
The larger content simply overflows the object's boundaries.
|
||||
It also means the layouts are not affected the by the transformations.
|
||||
|
||||
If you need the object size to be updated to the transformed size set `lv_img_set_size_mode(img, LV_IMG_SIZE_MODE_REAL)`. (The previous mode is the default and called `LV_IMG_SIZE_MODE_VIRTUAL`).
|
||||
In this case if the width/height of the object is set to `LV_SIZE_CONTENT` the object's size will be set to the zoomed and rotated size.
|
||||
If an explicit size is set then the overflowing content will be cropped.
|
||||
|
||||
## Events
|
||||
No special events are sent by image objects.
|
||||
|
@ -388,6 +388,8 @@ _lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t sta
|
||||
else if(lv_style_get_prop(style, LV_STYLE_MIN_HEIGHT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_MAX_HEIGHT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_BORDER_WIDTH, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ANGLE, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ZOOM, &v)) layout_diff = true;
|
||||
|
||||
if(layout_diff) {
|
||||
if(part_act == LV_PART_MAIN) {
|
||||
|
@ -132,8 +132,8 @@ typedef enum {
|
||||
LV_STYLE_TRANSFORM_HEIGHT = 11 | LV_STYLE_PROP_EXT_DRAW,
|
||||
LV_STYLE_TRANSLATE_X = 12 | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR,
|
||||
LV_STYLE_TRANSLATE_Y = 13 | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR,
|
||||
LV_STYLE_TRANSFORM_ZOOM = 14 | LV_STYLE_PROP_EXT_DRAW,
|
||||
LV_STYLE_TRANSFORM_ANGLE = 15 | LV_STYLE_PROP_EXT_DRAW,
|
||||
LV_STYLE_TRANSFORM_ZOOM = 14 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR,
|
||||
LV_STYLE_TRANSFORM_ANGLE = 15 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR,
|
||||
|
||||
/*Group 1*/
|
||||
LV_STYLE_PAD_TOP = 16 | LV_STYLE_PROP_LAYOUT_REFR,
|
||||
|
@ -291,6 +291,16 @@ void lv_img_set_antialias(lv_obj_t * obj, bool antialias)
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
void lv_img_set_size_mode(lv_obj_t * obj, lv_img_size_mode_t mode)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_img_t * img = (lv_img_t *)obj;
|
||||
if(mode == img->obj_size_mode) return;
|
||||
|
||||
img->obj_size_mode = mode;
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@ -358,6 +368,13 @@ bool lv_img_get_antialias(lv_obj_t * obj)
|
||||
return img->antialias ? true : false;
|
||||
}
|
||||
|
||||
lv_img_size_mode_t lv_img_get_size_mode(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_img_t * img = (lv_img_t *)obj;
|
||||
return img->obj_size_mode;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@ -381,6 +398,7 @@ static void lv_img_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
img->offset.y = 0;
|
||||
img->pivot.x = 0;
|
||||
img->pivot.y = 0;
|
||||
img->obj_size_mode = LV_IMG_SIZE_MODE_VIRTUAL;
|
||||
|
||||
lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_add_flag(obj, LV_OBJ_FLAG_ADV_HITTEST);
|
||||
@ -399,6 +417,22 @@ static void lv_img_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
}
|
||||
}
|
||||
|
||||
static lv_point_t lv_img_get_tranformed_size(lv_obj_t* obj)
|
||||
{
|
||||
lv_img_t * img = (lv_img_t *)obj;
|
||||
|
||||
int32_t zoom_final = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN);
|
||||
zoom_final = (zoom_final * img->zoom) >> 8;
|
||||
int32_t angle_final = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN);
|
||||
angle_final += img->angle;
|
||||
|
||||
lv_area_t area_transform;
|
||||
_lv_img_buf_get_transformed_area(&area_transform, img->w, img->h ,
|
||||
angle_final, zoom_final, &img->pivot);
|
||||
|
||||
return (lv_point_t){lv_area_get_width(&area_transform), lv_area_get_height(&area_transform)};
|
||||
}
|
||||
|
||||
static void lv_img_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
@ -477,9 +511,14 @@ static void lv_img_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_GET_SELF_SIZE) {
|
||||
lv_point_t * p = lv_event_get_param(e);;
|
||||
p->x = img->w;
|
||||
p->y = img->h;
|
||||
lv_point_t * p = lv_event_get_param(e);
|
||||
if (img->obj_size_mode == LV_IMG_SIZE_MODE_REAL){
|
||||
*p = lv_img_get_tranformed_size(obj);
|
||||
}
|
||||
else {
|
||||
p->x = img->w;
|
||||
p->y = img->h;
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_DRAW_MAIN || code == LV_EVENT_DRAW_POST || code == LV_EVENT_COVER_CHECK) {
|
||||
draw_img(e);
|
||||
@ -564,14 +603,21 @@ static void draw_img(lv_event_t * e)
|
||||
bg_pivot.x = img->pivot.x + pleft;
|
||||
bg_pivot.y = img->pivot.y + ptop;
|
||||
lv_area_t bg_coords;
|
||||
_lv_img_buf_get_transformed_area(&bg_coords, obj_w, obj_h,
|
||||
angle_final, zoom_final, &bg_pivot);
|
||||
|
||||
/*Modify the coordinates to draw the background for the rotated and scaled coordinates*/
|
||||
bg_coords.x1 += obj->coords.x1;
|
||||
bg_coords.y1 += obj->coords.y1;
|
||||
bg_coords.x2 += obj->coords.x1;
|
||||
bg_coords.y2 += obj->coords.y1;
|
||||
if (img->obj_size_mode == LV_IMG_SIZE_MODE_REAL) {
|
||||
/*Object size equals to transformed image size*/
|
||||
lv_obj_get_coords(obj, &bg_coords);
|
||||
}
|
||||
else {
|
||||
_lv_img_buf_get_transformed_area(&bg_coords, obj_w, obj_h,
|
||||
angle_final, zoom_final, &bg_pivot);
|
||||
|
||||
/*Modify the coordinates to draw the background for the rotated and scaled coordinates*/
|
||||
bg_coords.x1 += obj->coords.x1;
|
||||
bg_coords.y1 += obj->coords.y1;
|
||||
bg_coords.x2 += obj->coords.x1;
|
||||
bg_coords.y2 += obj->coords.y1;
|
||||
}
|
||||
|
||||
lv_area_t ori_coords;
|
||||
lv_area_copy(&ori_coords, &obj->coords);
|
||||
@ -590,6 +636,20 @@ static void draw_img(lv_event_t * e)
|
||||
|
||||
lv_area_t img_max_area;
|
||||
lv_area_copy(&img_max_area, &obj->coords);
|
||||
|
||||
lv_point_t img_size_final = lv_img_get_tranformed_size(obj);
|
||||
|
||||
if(img->obj_size_mode == LV_IMG_SIZE_MODE_REAL){
|
||||
img_max_area.x1 -= ((img->w - img_size_final.x) + 1) / 2;
|
||||
img_max_area.x2 -= ((img->w - img_size_final.x) + 1) / 2;
|
||||
img_max_area.y1 -= ((img->h - img_size_final.y) + 1) / 2;
|
||||
img_max_area.y2 -= ((img->h - img_size_final.y) + 1) / 2;
|
||||
}
|
||||
else {
|
||||
img_max_area.x2 = img_max_area.x1 + lv_area_get_width(&bg_coords) - 1;
|
||||
img_max_area.y2 = img_max_area.y1 + lv_area_get_height(&bg_coords) - 1;
|
||||
}
|
||||
|
||||
img_max_area.x1 += pleft;
|
||||
img_max_area.y1 += ptop;
|
||||
img_max_area.x2 -= pright;
|
||||
@ -619,12 +679,12 @@ static void draw_img(lv_event_t * e)
|
||||
if(coords_tmp.y1 > img_max_area.y1) coords_tmp.y1 -= img->h;
|
||||
coords_tmp.y2 = coords_tmp.y1 + img->h - 1;
|
||||
|
||||
for(; coords_tmp.y1 < img_max_area.y2; coords_tmp.y1 += img->h, coords_tmp.y2 += img->h) {
|
||||
for(; coords_tmp.y1 < img_max_area.y2; coords_tmp.y1 += img_size_final.y, coords_tmp.y2 += img_size_final.y) {
|
||||
coords_tmp.x1 = img_max_area.x1 + img->offset.x;
|
||||
if(coords_tmp.x1 > img_max_area.x1) coords_tmp.x1 -= img->w;
|
||||
coords_tmp.x2 = coords_tmp.x1 + img->w - 1;
|
||||
|
||||
for(; coords_tmp.x1 < img_max_area.x2; coords_tmp.x1 += img->w, coords_tmp.x2 += img->w) {
|
||||
for(; coords_tmp.x1 < img_max_area.x2; coords_tmp.x1 += img_size_final.x, coords_tmp.x2 += img_size_final.x) {
|
||||
lv_draw_img(&coords_tmp, &img_clip_area, img->src, &img_dsc);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,10 @@ extern "C" {
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Data of image*/
|
||||
|
||||
/**
|
||||
* Data of image
|
||||
*/
|
||||
typedef struct {
|
||||
lv_obj_t obj;
|
||||
const void * src; /*Image source: Pointer to an array or a file or a symbol*/
|
||||
@ -41,10 +44,28 @@ typedef struct {
|
||||
uint8_t src_type : 2; /*See: lv_img_src_t*/
|
||||
uint8_t cf : 5; /*Color format from `lv_img_color_format_t`*/
|
||||
uint8_t antialias : 1; /*Apply anti-aliasing in transformations (rotate, zoom)*/
|
||||
uint8_t obj_size_mode: 2; /*Image size mode when image size and object size is different.*/
|
||||
} lv_img_t;
|
||||
|
||||
extern const lv_obj_class_t lv_img_class;
|
||||
|
||||
/**
|
||||
* Image size mode, when image size and object size is different
|
||||
*/
|
||||
enum {
|
||||
/** Zoom doesn't affect the coordinates of the object,
|
||||
* however if zoomed in the image is drawn out of the its coordinates.
|
||||
* The layout's won't change on zoom */
|
||||
LV_IMG_SIZE_MODE_VIRTUAL = 0,
|
||||
|
||||
/** If the object size is set to SIZE_CONTENT, then object size equals zoomed image size.
|
||||
* It causes layout recalculation.
|
||||
* If the object size is set explicitly the the image will be cropped if zoomed in.*/
|
||||
LV_IMG_SIZE_MODE_REAL,
|
||||
};
|
||||
|
||||
typedef uint8_t lv_img_size_mode_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
@ -123,6 +144,13 @@ void lv_img_set_zoom(lv_obj_t * obj, uint16_t zoom);
|
||||
*/
|
||||
void lv_img_set_antialias(lv_obj_t * obj, bool antialias);
|
||||
|
||||
/**
|
||||
* Set the image object size mode.
|
||||
*
|
||||
* @param obj pointer to an image object
|
||||
* @param mode the new size mode.
|
||||
*/
|
||||
void lv_img_set_size_mode(lv_obj_t * obj, lv_img_size_mode_t mode);
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@ -176,6 +204,13 @@ uint16_t lv_img_get_zoom(lv_obj_t * obj);
|
||||
*/
|
||||
bool lv_img_get_antialias(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the size mode of the image
|
||||
* @param obj pointer to an image object
|
||||
* @return element of @ref lv_img_size_mode_t
|
||||
*/
|
||||
lv_img_size_mode_t lv_img_get_size_mode(lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
Loading…
x
Reference in New Issue
Block a user