feat(iamge) add scale_x and scale_y support

This commit is contained in:
Gabor Kiss-Vamosi
2023-10-26 12:09:53 +02:00
parent 726620d0fc
commit bbb56e6849
2 changed files with 143 additions and 50 deletions
+100 -49
View File
@@ -27,6 +27,7 @@ static void lv_image_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
static void lv_image_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
static void lv_image_event(const lv_obj_class_t * class_p, lv_event_t * e);
static void draw_image(lv_event_t * e);
static void scale_update(lv_obj_t * obj, int32_t zoom_x, int32_t zoom_y);
#if LV_USE_OBJ_PROPERTY
static const lv_property_ops_t properties[] = {
@@ -198,7 +199,7 @@ void lv_image_set_src(lv_obj_t * obj, const void * src)
lv_obj_refresh_self_size(obj);
/*Provide enough room for the rotated corners*/
if(img->rotation || img->zoom != LV_SCALE_NONE) lv_obj_refresh_ext_draw_size(obj);
if(img->rotation || img->zoom_x != LV_SCALE_NONE || img->zoom_y != LV_SCALE_NONE) lv_obj_refresh_ext_draw_size(obj);
lv_obj_invalidate(obj);
}
@@ -243,7 +244,7 @@ void lv_image_set_rotation(lv_obj_t * obj, int32_t angle)
lv_area_t a;
lv_point_t pivot_px;
lv_image_get_pivot(obj, &pivot_px);
_lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom, img->zoom, &pivot_px);
_lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px);
a.x1 += obj->coords.x1;
a.y1 += obj->coords.y1;
a.x2 += obj->coords.x1;
@@ -259,7 +260,7 @@ void lv_image_set_rotation(lv_obj_t * obj, int32_t angle)
lv_obj_refresh_ext_draw_size(obj);
lv_display_enable_invalidation(disp, true);
_lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom, img->zoom, &pivot_px);
_lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px);
a.x1 += obj->coords.x1;
a.y1 += obj->coords.y1;
a.x2 += obj->coords.x1;
@@ -285,7 +286,7 @@ void lv_image_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y)
lv_area_t a;
lv_point_t pivot_px;
lv_image_get_pivot(obj, &pivot_px);
_lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom, img->zoom, &pivot_px);
_lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px);
a.x1 += obj->coords.x1;
a.y1 += obj->coords.y1;
a.x2 += obj->coords.x1;
@@ -303,7 +304,7 @@ void lv_image_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y)
lv_display_enable_invalidation(disp, true);
lv_image_get_pivot(obj, &pivot_px);
_lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom, img->zoom, &pivot_px);
_lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px);
a.x1 += obj->coords.x1;
a.y1 += obj->coords.y1;
a.x2 += obj->coords.x1;
@@ -314,44 +315,31 @@ void lv_image_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y)
void lv_image_set_scale(lv_obj_t * obj, uint32_t zoom)
{
lv_image_t * img = (lv_image_t *)obj;
if(zoom == img->zoom) return;
if(zoom == img->zoom_x && zoom == img->zoom_y) return;
if(zoom == 0) zoom = 1;
if(img->obj_size_mode == LV_IMAGE_SIZE_MODE_REAL) {
img->zoom = zoom;
lv_obj_invalidate_area(obj, &obj->coords);
return;
}
scale_update(obj, zoom, zoom);
}
lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/
lv_coord_t w = lv_obj_get_width(obj);
lv_coord_t h = lv_obj_get_height(obj);
lv_area_t a;
lv_point_t pivot_px;
lv_image_get_pivot(obj, &pivot_px);
_lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom, img->zoom, &pivot_px);
a.x1 += obj->coords.x1 - 1;
a.y1 += obj->coords.y1 - 1;
a.x2 += obj->coords.x1 + 1;
a.y2 += obj->coords.y1 + 1;
lv_obj_invalidate_area(obj, &a);
void lv_image_set_scale_x(lv_obj_t * obj, uint32_t zoom)
{
lv_image_t * img = (lv_image_t *)obj;
if(zoom == img->zoom_x) return;
img->zoom = zoom;
if(zoom == 0) zoom = 1;
/* Disable invalidations because lv_obj_refresh_ext_draw_size would invalidate
* the whole ext draw area */
lv_display_t * disp = lv_obj_get_disp(obj);
lv_display_enable_invalidation(disp, false);
lv_obj_refresh_ext_draw_size(obj);
lv_display_enable_invalidation(disp, true);
scale_update(obj, zoom, img->zoom_y);
}
_lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom, img->zoom, &pivot_px);
a.x1 += obj->coords.x1 - 1;
a.y1 += obj->coords.y1 - 1;
a.x2 += obj->coords.x1 + 1;
a.y2 += obj->coords.y1 + 1;
lv_obj_invalidate_area(obj, &a);
void lv_image_set_scale_y(lv_obj_t * obj, uint32_t zoom)
{
lv_image_t * img = (lv_image_t *)obj;
if(zoom == img->zoom_y) return;
if(zoom == 0) zoom = 1;
scale_update(obj, img->zoom_y, zoom);
}
void lv_image_set_antialias(lv_obj_t * obj, bool antialias)
@@ -429,7 +417,25 @@ lv_coord_t lv_image_get_scale(lv_obj_t * obj)
lv_image_t * img = (lv_image_t *)obj;
return img->zoom;
return img->zoom_x;
}
lv_coord_t lv_image_get_scale_x(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_image_t * img = (lv_image_t *)obj;
return img->zoom_x;
}
lv_coord_t lv_image_get_scale_y(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_image_t * img = (lv_image_t *)obj;
return img->zoom_y;
}
bool lv_image_get_antialias(lv_obj_t * obj)
@@ -465,7 +471,8 @@ static void lv_image_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
img->w = lv_obj_get_width(obj);
img->h = lv_obj_get_height(obj);
img->rotation = 0;
img->zoom = LV_SCALE_NONE;
img->zoom_x = LV_SCALE_NONE;
img->zoom_y = LV_SCALE_NONE;
img->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0;
img->offset.x = 0;
img->offset.y = 0;
@@ -500,7 +507,7 @@ static lv_point_t lv_image_get_transformed_size(lv_obj_t * obj)
lv_point_t pivot_px;
lv_image_get_pivot(obj, &pivot_px);
_lv_image_buf_get_transformed_area(&area_transform, img->w, img->h,
img->rotation, img->zoom, img->zoom, &pivot_px);
img->rotation, img->zoom_x, img->zoom_y, &pivot_px);
return (lv_point_t) {
lv_area_get_width(&area_transform), lv_area_get_height(&area_transform)
@@ -540,11 +547,11 @@ static void lv_image_event(const lv_obj_class_t * class_p, lv_event_t * e)
lv_coord_t * s = lv_event_get_param(e);
/*If the image has angle provide enough room for the rotated corners*/
if(img->rotation || img->zoom != LV_SCALE_NONE) {
if(img->rotation || img->zoom_x != LV_SCALE_NONE || img->zoom_y != LV_SCALE_NONE) {
lv_area_t a;
lv_coord_t w = lv_obj_get_width(obj);
lv_coord_t h = lv_obj_get_height(obj);
_lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom, img->zoom, &pivot_px);
_lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px);
*s = LV_MAX(*s, -a.x1);
*s = LV_MAX(*s, -a.y1);
*s = LV_MAX(*s, a.x2 - w);
@@ -557,12 +564,13 @@ static void lv_image_event(const lv_obj_class_t * class_p, lv_event_t * e)
/*If the object is exactly image sized (not cropped, not mosaic) and transformed
*perform hit test on its transformed area*/
if(img->w == lv_obj_get_width(obj) && img->h == lv_obj_get_height(obj) &&
(img->zoom != LV_SCALE_NONE || img->rotation != 0 || img->pivot.x != img->w / 2 || img->pivot.y != img->h / 2)) {
(img->zoom_x != LV_SCALE_NONE || img->zoom_y != LV_SCALE_NONE ||
img->rotation != 0 || img->pivot.x != img->w / 2 || img->pivot.y != img->h / 2)) {
lv_coord_t w = lv_obj_get_width(obj);
lv_coord_t h = lv_obj_get_height(obj);
lv_area_t coords;
_lv_image_buf_get_transformed_area(&coords, w, h, img->rotation, img->zoom, img->zoom, &pivot_px);
_lv_image_buf_get_transformed_area(&coords, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px);
coords.x1 += obj->coords.x1;
coords.y1 += obj->coords.y1;
coords.x2 += obj->coords.x1;
@@ -622,7 +630,7 @@ static void draw_image(lv_event_t * e)
}
const lv_area_t * clip_area = lv_event_get_param(e);
if(img->zoom == LV_SCALE_NONE) {
if(img->zoom_x == LV_SCALE_NONE && img->zoom_y == LV_SCALE_NONE) {
if(_lv_area_is_in(clip_area, &obj->coords, 0) == false) {
info->res = LV_COVER_RES_NOT_COVER;
return;
@@ -632,7 +640,7 @@ static void draw_image(lv_event_t * e)
lv_area_t a;
lv_point_t pivot_px;
lv_image_get_pivot(obj, &pivot_px);
_lv_image_buf_get_transformed_area(&a, lv_obj_get_width(obj), lv_obj_get_height(obj), 0, img->zoom, img->zoom,
_lv_image_buf_get_transformed_area(&a, lv_obj_get_width(obj), lv_obj_get_height(obj), 0, img->zoom_x, img->zoom_y,
&pivot_px);
a.x1 += obj->coords.x1;
a.y1 += obj->coords.y1;
@@ -670,7 +678,7 @@ static void draw_image(lv_event_t * e)
}
else {
_lv_image_buf_get_transformed_area(&bg_coords, obj_w, obj_h,
img->rotation, img->zoom, img->zoom, &bg_pivot);
img->rotation, img->zoom_x, img->zoom_y, &bg_pivot);
/*Modify the coordinates to draw the background for the rotated and scaled coordinates*/
bg_coords.x1 += obj->coords.x1;
@@ -690,7 +698,7 @@ static void draw_image(lv_event_t * e)
if(code == LV_EVENT_DRAW_MAIN) {
if(img->h == 0 || img->w == 0) return;
if(img->zoom == 0) return;
if(img->zoom_x == 0 || img->zoom_y == 0) return;
lv_layer_t * layer = lv_event_get_layer(e);
@@ -720,8 +728,8 @@ static void draw_image(lv_event_t * e)
lv_draw_image_dsc_init(&img_dsc);
lv_obj_init_draw_image_dsc(obj, LV_PART_MAIN, &img_dsc);
img_dsc.zoom_x = img->zoom;
img_dsc.zoom_y = img->zoom;
img_dsc.zoom_x = img->zoom_x;
img_dsc.zoom_y = img->zoom_y;
img_dsc.rotation = img->rotation;
img_dsc.pivot.x = pivot_px.x;
img_dsc.pivot.y = pivot_px.y;
@@ -775,4 +783,47 @@ static void draw_image(lv_event_t * e)
}
}
static void scale_update(lv_obj_t * obj, int32_t zoom_x, int32_t zoom_y)
{
lv_image_t * img = (lv_image_t *)obj;
if(img->obj_size_mode == LV_IMAGE_SIZE_MODE_REAL) {
img->zoom_x = zoom_x;
img->zoom_y = zoom_y;
lv_obj_invalidate_area(obj, &obj->coords);
return;
}
lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/
lv_coord_t w = lv_obj_get_width(obj);
lv_coord_t h = lv_obj_get_height(obj);
lv_area_t a;
lv_point_t pivot_px;
lv_image_get_pivot(obj, &pivot_px);
_lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px);
a.x1 += obj->coords.x1 - 1;
a.y1 += obj->coords.y1 - 1;
a.x2 += obj->coords.x1 + 1;
a.y2 += obj->coords.y1 + 1;
lv_obj_invalidate_area(obj, &a);
img->zoom_x = zoom_x;
img->zoom_y = zoom_y;
/* Disable invalidations because lv_obj_refresh_ext_draw_size would invalidate
* the whole ext draw area */
lv_display_t * disp = lv_obj_get_disp(obj);
lv_display_enable_invalidation(disp, false);
lv_obj_refresh_ext_draw_size(obj);
lv_display_enable_invalidation(disp, true);
_lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px);
a.x1 += obj->coords.x1 - 1;
a.y1 += obj->coords.y1 - 1;
a.x2 += obj->coords.x1 + 1;
a.y2 += obj->coords.y1 + 1;
lv_obj_invalidate_area(obj, &a);
}
#endif
+43 -1
View File
@@ -44,7 +44,8 @@ typedef struct {
lv_coord_t w; /*Width of the image (Handled by the library)*/
lv_coord_t h; /*Height of the image (Handled by the library)*/
uint32_t rotation; /*rotation angle of the image*/
uint32_t zoom; /*256 means no zoom, 512 double size, 128 half size*/
uint32_t zoom_x; /*256 means no zoom, 512 double size, 128 half size*/
uint32_t zoom_y; /*256 means no zoom, 512 double size, 128 half size*/
lv_point_t pivot; /*rotation center of the image*/
uint8_t src_type : 2; /*See: lv_image_src_t*/
uint8_t cf : 5; /*Color format from `lv_color_format_t`*/
@@ -170,6 +171,33 @@ static inline void _lv_image_set_pivot(lv_obj_t * obj, lv_point_t * pivot)
*/
void lv_image_set_scale(lv_obj_t * obj, uint32_t zoom);
/**
* Set the horizontal zoom factor of the image.
* Note that indexed and alpha only images can't be transformed.
* @param img pointer to an image object
* @param zoom the zoom factor.
* @example 256 or LV_ZOOM_IMAGE_NONE for no zoom
* @example <256: scale down
* @example >256 scale up
* @example 128 half size
* @example 512 double size
*/
void lv_image_set_scale_x(lv_obj_t * obj, uint32_t zoom);
/**
* Set the vertical zoom factor of the image.
* Note that indexed and alpha only images can't be transformed.
* @param img pointer to an image object
* @param zoom the zoom factor.
* @example 256 or LV_ZOOM_IMAGE_NONE for no zoom
* @example <256: scale down
* @example >256 scale up
* @example 128 half size
* @example 512 double size
*/
void lv_image_set_scale_y(lv_obj_t * obj, uint32_t zoom);
/**
* Enable/disable anti-aliasing for the transformations (rotate, zoom) or not.
* The quality is better with anti-aliasing looks better but slower.
@@ -232,6 +260,20 @@ void lv_image_get_pivot(lv_obj_t * obj, lv_point_t * pivot);
*/
lv_coord_t lv_image_get_scale(lv_obj_t * obj);
/**
* Get the horizontal zoom factor of the image.
* @param obj pointer to an image object
* @return zoom factor (256: no zoom)
*/
lv_coord_t lv_image_get_scale_x(lv_obj_t * obj);
/**
* Get the vertical zoom factor of the image.
* @param obj pointer to an image object
* @return zoom factor (256: no zoom)
*/
lv_coord_t lv_image_get_scale_y(lv_obj_t * obj);
/**
* Get whether the transformations (rotate, zoom) are anti-aliased or not
* @param obj pointer to an image object