feat(image): add lv_image_align_t to stretch, tile, and align images
related to #4733
@ -56,6 +56,7 @@ typedef struct _lv_draw_image_dsc_t {
|
||||
|
||||
int32_t frame_id;
|
||||
uint16_t antialias : 1;
|
||||
uint16_t tile : 1;
|
||||
lv_draw_image_sup_t * sup;
|
||||
} lv_draw_image_dsc_t;
|
||||
|
||||
|
@ -32,8 +32,20 @@
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void img_draw_core(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, const lv_area_t * draw_area,
|
||||
const lv_image_decoder_dsc_t * src, lv_draw_image_sup_t * sup, const lv_area_t * img_coords);
|
||||
|
||||
static void img_draw_normal(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
static void img_draw_tiled(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
static void img_decode_and_draw(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||
lv_image_decoder_dsc_t * decoder_dsc,
|
||||
const lv_area_t * img_area, const lv_area_t * clipped_img_area);
|
||||
|
||||
static void img_draw_core(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup,
|
||||
const lv_area_t * img_coords, const lv_area_t * clipped_img_area);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@ -149,29 +161,37 @@ void lv_draw_sw_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dr
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_image(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
lv_area_t transformed_area;
|
||||
lv_area_copy(&transformed_area, coords);
|
||||
if(!draw_dsc->tile) {
|
||||
img_draw_normal(draw_unit, draw_dsc, coords);
|
||||
}
|
||||
else {
|
||||
img_draw_tiled(draw_unit, draw_dsc, coords);
|
||||
}
|
||||
}
|
||||
|
||||
static void img_draw_normal(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
lv_area_t draw_area;
|
||||
lv_area_copy(&draw_area, coords);
|
||||
if(draw_dsc->rotation || draw_dsc->scale_x != LV_SCALE_NONE || draw_dsc->scale_y != LV_SCALE_NONE) {
|
||||
int32_t w = lv_area_get_width(coords);
|
||||
int32_t h = lv_area_get_height(coords);
|
||||
|
||||
_lv_image_buf_get_transformed_area(&transformed_area, w, h, draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y,
|
||||
_lv_image_buf_get_transformed_area(&draw_area, w, h, draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y,
|
||||
&draw_dsc->pivot);
|
||||
|
||||
transformed_area.x1 += coords->x1;
|
||||
transformed_area.y1 += coords->y1;
|
||||
transformed_area.x2 += coords->x1;
|
||||
transformed_area.y2 += coords->y1;
|
||||
draw_area.x1 += coords->x1;
|
||||
draw_area.y1 += coords->y1;
|
||||
draw_area.x2 += coords->x1;
|
||||
draw_area.y2 += coords->y1;
|
||||
}
|
||||
|
||||
lv_area_t draw_area; /*Common area of cilp_area and coords. The image is visible only here*/
|
||||
/*Out of mask. There is nothing to draw so the image is drawn successfully.*/
|
||||
if(!_lv_area_intersect(&draw_area, draw_unit->clip_area, &transformed_area)) {
|
||||
lv_area_t clipped_img_area;
|
||||
if(!_lv_area_intersect(&clipped_img_area, &draw_area, draw_unit->clip_area)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -182,56 +202,100 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_image(lv_draw_unit_t * draw_unit, const lv
|
||||
return;
|
||||
}
|
||||
|
||||
img_decode_and_draw(draw_unit, draw_dsc, &decoder_dsc, coords, &clipped_img_area);
|
||||
|
||||
lv_image_decoder_close(&decoder_dsc);
|
||||
}
|
||||
|
||||
static void img_draw_tiled(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
lv_image_decoder_dsc_t decoder_dsc;
|
||||
lv_result_t res = lv_image_decoder_open(&decoder_dsc, draw_dsc->src, draw_dsc->recolor, -1);
|
||||
if(res != LV_RESULT_OK) {
|
||||
LV_LOG_ERROR("Failed to open image");
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t img_w = lv_area_get_width(coords);
|
||||
int32_t img_h = lv_area_get_height(coords);
|
||||
|
||||
lv_area_t tile_area = *coords;
|
||||
int32_t tile_x_start = tile_area.x1;
|
||||
|
||||
while(tile_area.y1 < draw_unit->clip_area->y2) {
|
||||
while(tile_area.x1 < draw_unit->clip_area->x2) {
|
||||
|
||||
lv_area_t clipped_img_area;
|
||||
if(_lv_area_intersect(&clipped_img_area, &tile_area, draw_unit->clip_area)) {
|
||||
img_decode_and_draw(draw_unit, draw_dsc, &decoder_dsc, &tile_area, &clipped_img_area);
|
||||
}
|
||||
|
||||
tile_area.x1 += img_w;
|
||||
tile_area.x2 += img_w;
|
||||
}
|
||||
|
||||
tile_area.y1 += img_h;
|
||||
tile_area.y2 += img_h;
|
||||
tile_area.x1 = tile_x_start;
|
||||
tile_area.x2 = tile_x_start + img_w - 1;
|
||||
}
|
||||
|
||||
lv_image_decoder_close(&decoder_dsc);
|
||||
}
|
||||
|
||||
static void img_decode_and_draw(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||
lv_image_decoder_dsc_t * decoder_dsc,
|
||||
const lv_area_t * img_area, const lv_area_t * clipped_img_area)
|
||||
{
|
||||
lv_draw_image_sup_t sup;
|
||||
sup.alpha_color = draw_dsc->recolor;
|
||||
sup.palette = decoder_dsc.palette;
|
||||
sup.palette_size = decoder_dsc.palette_size;
|
||||
sup.palette = decoder_dsc->palette;
|
||||
sup.palette_size = decoder_dsc->palette_size;
|
||||
|
||||
/*The whole image is available, just draw it*/
|
||||
if(decoder_dsc.img_data) {
|
||||
img_draw_core(draw_unit, draw_dsc, &draw_area, &decoder_dsc,
|
||||
&sup, coords);
|
||||
if(decoder_dsc->img_data) {
|
||||
img_draw_core(draw_unit, draw_dsc, decoder_dsc, &sup, img_area, clipped_img_area);
|
||||
}
|
||||
/*Draw line by line*/
|
||||
/*Draw in smaller pieces*/
|
||||
else {
|
||||
lv_area_t relative_full_area_to_decode = draw_area;
|
||||
lv_area_move(&relative_full_area_to_decode, -coords->x1, -coords->y1);
|
||||
lv_area_t relative_full_area_to_decode = *clipped_img_area;
|
||||
lv_area_move(&relative_full_area_to_decode, -img_area->x1, -img_area->y1);
|
||||
|
||||
lv_area_t relative_decoded_area;
|
||||
relative_decoded_area.x1 = LV_COORD_MIN;
|
||||
relative_decoded_area.y1 = LV_COORD_MIN;
|
||||
relative_decoded_area.x2 = LV_COORD_MIN;
|
||||
relative_decoded_area.y2 = LV_COORD_MIN;
|
||||
res = LV_RESULT_OK;
|
||||
lv_result_t res = LV_RESULT_OK;
|
||||
|
||||
while(res == LV_RESULT_OK) {
|
||||
res = lv_image_decoder_get_area(&decoder_dsc, &relative_full_area_to_decode, &relative_decoded_area);
|
||||
res = lv_image_decoder_get_area(decoder_dsc, &relative_full_area_to_decode, &relative_decoded_area);
|
||||
|
||||
lv_area_t absolute_decoded_area = relative_decoded_area;
|
||||
lv_area_move(&absolute_decoded_area, coords->x1, coords->y1);
|
||||
lv_area_move(&absolute_decoded_area, img_area->x1, img_area->y1);
|
||||
if(res == LV_RESULT_OK) {
|
||||
/*Limit draw area to the current decoded area and draw the image*/
|
||||
lv_area_t draw_area_sub;
|
||||
if(_lv_area_intersect(&draw_area_sub, &draw_area, &absolute_decoded_area)) {
|
||||
img_draw_core(draw_unit, draw_dsc, &draw_area_sub, &decoder_dsc,
|
||||
&sup, &absolute_decoded_area);
|
||||
lv_area_t clipped_img_area_sub;
|
||||
if(_lv_area_intersect(&clipped_img_area_sub, clipped_img_area, &absolute_decoded_area)) {
|
||||
img_draw_core(draw_unit, draw_dsc, decoder_dsc, &sup,
|
||||
&absolute_decoded_area, &clipped_img_area_sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lv_image_decoder_close(&decoder_dsc);
|
||||
}
|
||||
|
||||
|
||||
static void img_draw_core(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, const lv_area_t * draw_area,
|
||||
const lv_image_decoder_dsc_t * src, lv_draw_image_sup_t * sup, const lv_area_t * img_coords)
|
||||
static void img_draw_core(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup,
|
||||
const lv_area_t * img_coords, const lv_area_t * clipped_img_area)
|
||||
{
|
||||
bool transformed = draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE ||
|
||||
draw_dsc->scale_y != LV_SCALE_NONE ? true : false;
|
||||
|
||||
lv_draw_sw_blend_dsc_t blend_dsc;
|
||||
const uint8_t * src_buf = src->img_data;
|
||||
const lv_image_header_t * header = &src->header;
|
||||
const uint8_t * src_buf = decoder_dsc->img_data;
|
||||
const lv_image_header_t * header = &decoder_dsc->header;
|
||||
uint32_t img_stride = header->stride;
|
||||
lv_color_format_t cf = header->cf;
|
||||
|
||||
@ -280,7 +344,7 @@ static void img_draw_core(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t
|
||||
}
|
||||
/*In the other cases every pixel need to be checked one-by-one*/
|
||||
else {
|
||||
lv_area_t blend_area = *draw_area;
|
||||
lv_area_t blend_area = *clipped_img_area;
|
||||
blend_dsc.blend_area = &blend_area;
|
||||
|
||||
int32_t src_w = lv_area_get_width(img_coords);
|
||||
|
@ -188,6 +188,7 @@ static void lv_barcode_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob
|
||||
barcode->light_color = lv_color_white();
|
||||
barcode->scale = 1;
|
||||
barcode->direction = LV_DIR_HOR;
|
||||
lv_image_set_align(obj, LV_IMAGE_ALIGN_TILE);
|
||||
}
|
||||
|
||||
static void lv_barcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
|
@ -28,6 +28,7 @@ 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 scale_x, int32_t scale_y);
|
||||
static void update_align(lv_obj_t * obj);
|
||||
|
||||
#if LV_USE_OBJ_PROPERTY
|
||||
static const lv_property_ops_t properties[] = {
|
||||
@ -67,9 +68,9 @@ static const lv_property_ops_t properties[] = {
|
||||
.getter = lv_image_get_antialias,
|
||||
},
|
||||
{
|
||||
.id = LV_PROPERTY_IMAGE_SIZE_MODE,
|
||||
.setter = lv_image_set_size_mode,
|
||||
.getter = lv_image_get_size_mode,
|
||||
.id = LV_PROPERTY_IMAGE_ALIGN,
|
||||
.setter = lv_image_set_align,
|
||||
.getter = lv_image_get_align,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
@ -204,8 +205,12 @@ void lv_image_set_src(lv_obj_t * obj, const void * src)
|
||||
|
||||
lv_obj_refresh_self_size(obj);
|
||||
|
||||
update_align(obj);
|
||||
|
||||
/*Provide enough room for the rotated corners*/
|
||||
if(img->rotation || img->scale_x != LV_SCALE_NONE || img->scale_y != LV_SCALE_NONE) lv_obj_refresh_ext_draw_size(obj);
|
||||
if(img->rotation || img->scale_x != LV_SCALE_NONE || img->scale_y != LV_SCALE_NONE) {
|
||||
lv_obj_refresh_ext_draw_size(obj);
|
||||
}
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
@ -232,17 +237,17 @@ void lv_image_set_offset_y(lv_obj_t * obj, int32_t y)
|
||||
|
||||
void lv_image_set_rotation(lv_obj_t * obj, int32_t angle)
|
||||
{
|
||||
while(angle >= 3600) angle -= 3600;
|
||||
while(angle < 0) angle += 3600;
|
||||
|
||||
lv_image_t * img = (lv_image_t *)obj;
|
||||
if((uint32_t)angle == img->rotation) return;
|
||||
|
||||
if(img->obj_size_mode == LV_IMAGE_SIZE_MODE_REAL) {
|
||||
img->rotation = angle;
|
||||
lv_obj_invalidate_area(obj, &obj->coords);
|
||||
return;
|
||||
if(img->align > _LV_IMAGE_ALIGN_AUTO_TRANSFORM) {
|
||||
angle = 0;
|
||||
}
|
||||
else {
|
||||
while(angle >= 3600) angle -= 3600;
|
||||
while(angle < 0) angle += 3600;
|
||||
}
|
||||
|
||||
if((uint32_t)angle == img->rotation) return;
|
||||
|
||||
lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/
|
||||
int32_t w = lv_obj_get_width(obj);
|
||||
@ -277,15 +282,13 @@ void lv_image_set_rotation(lv_obj_t * obj, int32_t angle)
|
||||
void lv_image_set_pivot(lv_obj_t * obj, int32_t x, int32_t y)
|
||||
{
|
||||
lv_image_t * img = (lv_image_t *)obj;
|
||||
if(img->pivot.x == x && img->pivot.y == y) return;
|
||||
|
||||
if(img->obj_size_mode == LV_IMAGE_SIZE_MODE_REAL) {
|
||||
img->pivot.x = x;
|
||||
img->pivot.y = y;
|
||||
lv_obj_invalidate_area(obj, &obj->coords);
|
||||
return;
|
||||
if(img->align > _LV_IMAGE_ALIGN_AUTO_TRANSFORM) {
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if(img->pivot.x == x && img->pivot.y == y) return;
|
||||
|
||||
lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/
|
||||
int32_t w = lv_obj_get_width(obj);
|
||||
int32_t h = lv_obj_get_height(obj);
|
||||
@ -321,6 +324,10 @@ void lv_image_set_pivot(lv_obj_t * obj, int32_t x, int32_t y)
|
||||
void lv_image_set_scale(lv_obj_t * obj, uint32_t zoom)
|
||||
{
|
||||
lv_image_t * img = (lv_image_t *)obj;
|
||||
|
||||
/*If scale is set internally, do no overwrite it*/
|
||||
if(img->align > _LV_IMAGE_ALIGN_AUTO_TRANSFORM) return;
|
||||
|
||||
if(zoom == img->scale_x && zoom == img->scale_y) return;
|
||||
|
||||
if(zoom == 0) zoom = 1;
|
||||
@ -331,6 +338,10 @@ void lv_image_set_scale(lv_obj_t * obj, uint32_t zoom)
|
||||
void lv_image_set_scale_x(lv_obj_t * obj, uint32_t zoom)
|
||||
{
|
||||
lv_image_t * img = (lv_image_t *)obj;
|
||||
|
||||
/*If scale is set internally, do no overwrite it*/
|
||||
if(img->align > _LV_IMAGE_ALIGN_AUTO_TRANSFORM) return;
|
||||
|
||||
if(zoom == img->scale_x) return;
|
||||
|
||||
if(zoom == 0) zoom = 1;
|
||||
@ -341,6 +352,10 @@ void lv_image_set_scale_x(lv_obj_t * obj, uint32_t zoom)
|
||||
void lv_image_set_scale_y(lv_obj_t * obj, uint32_t zoom)
|
||||
{
|
||||
lv_image_t * img = (lv_image_t *)obj;
|
||||
|
||||
/*If scale is set internally, do no overwrite it*/
|
||||
if(img->align > _LV_IMAGE_ALIGN_AUTO_TRANSFORM) return;
|
||||
|
||||
if(zoom == img->scale_y) return;
|
||||
|
||||
if(zoom == 0) zoom = 1;
|
||||
@ -357,13 +372,16 @@ void lv_image_set_antialias(lv_obj_t * obj, bool antialias)
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
void lv_image_set_size_mode(lv_obj_t * obj, lv_image_size_mode_t mode)
|
||||
void lv_image_set_align(lv_obj_t * obj, lv_image_align_t align)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_image_t * img = (lv_image_t *)obj;
|
||||
if(mode == img->obj_size_mode) return;
|
||||
if(align == img->align) return;
|
||||
|
||||
img->align = align;
|
||||
|
||||
update_align(obj);
|
||||
|
||||
img->obj_size_mode = mode;
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
@ -453,11 +471,11 @@ bool lv_image_get_antialias(lv_obj_t * obj)
|
||||
return img->antialias ? true : false;
|
||||
}
|
||||
|
||||
lv_image_size_mode_t lv_image_get_size_mode(lv_obj_t * obj)
|
||||
lv_image_align_t lv_image_get_align(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_image_t * img = (lv_image_t *)obj;
|
||||
return img->obj_size_mode;
|
||||
return img->align;
|
||||
}
|
||||
|
||||
/**********************
|
||||
@ -484,7 +502,7 @@ static void lv_image_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
img->offset.y = 0;
|
||||
img->pivot.x = LV_PCT(50); /*Default pivot to image center*/
|
||||
img->pivot.y = LV_PCT(50);
|
||||
img->obj_size_mode = LV_IMAGE_SIZE_MODE_VIRTUAL;
|
||||
img->align = LV_IMAGE_ALIGN_CENTER;
|
||||
|
||||
lv_obj_remove_flag(obj, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_add_flag(obj, LV_OBJ_FLAG_ADV_HITTEST);
|
||||
@ -503,35 +521,15 @@ static void lv_image_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
}
|
||||
}
|
||||
|
||||
static lv_point_t lv_image_get_transformed_size(lv_obj_t * obj)
|
||||
{
|
||||
lv_image_t * img = (lv_image_t *)obj;
|
||||
|
||||
|
||||
lv_area_t area_transform;
|
||||
|
||||
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->scale_x, img->scale_y, &pivot_px);
|
||||
|
||||
return (lv_point_t) {
|
||||
lv_area_get_width(&area_transform), lv_area_get_height(&area_transform)
|
||||
};
|
||||
}
|
||||
|
||||
static void lv_image_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
|
||||
/*Ancestor events will be called during drawing*/
|
||||
if(code != LV_EVENT_DRAW_MAIN && code != LV_EVENT_DRAW_POST) {
|
||||
/*Call the ancestor's event handler*/
|
||||
lv_result_t res = lv_obj_event_base(MY_CLASS, e);
|
||||
if(res != LV_RESULT_OK) return;
|
||||
}
|
||||
/*Call the ancestor's event handler*/
|
||||
lv_result_t res = lv_obj_event_base(MY_CLASS, e);
|
||||
if(res != LV_RESULT_OK) return;
|
||||
|
||||
lv_obj_t * obj = lv_event_get_target(e);
|
||||
lv_image_t * img = (lv_image_t *)obj;
|
||||
@ -592,13 +590,8 @@ static void lv_image_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);
|
||||
if(img->obj_size_mode == LV_IMAGE_SIZE_MODE_REAL) {
|
||||
*p = lv_image_get_transformed_size(obj);
|
||||
}
|
||||
else {
|
||||
p->x = img->w;
|
||||
p->y = img->h;
|
||||
}
|
||||
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_image(e);
|
||||
@ -659,132 +652,61 @@ static void draw_image(lv_event_t * e)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_DRAW_MAIN || code == LV_EVENT_DRAW_POST) {
|
||||
else if(code == LV_EVENT_DRAW_MAIN) {
|
||||
|
||||
int32_t obj_w = lv_obj_get_width(obj);
|
||||
int32_t obj_h = lv_obj_get_height(obj);
|
||||
if(img->h == 0 || img->w == 0) return;
|
||||
if(img->scale_x == 0 || img->scale_y == 0) return;
|
||||
|
||||
int32_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN);
|
||||
int32_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width;
|
||||
int32_t pright = lv_obj_get_style_pad_right(obj, LV_PART_MAIN) + border_width;
|
||||
int32_t ptop = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width;
|
||||
int32_t pbottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN) + border_width;
|
||||
lv_layer_t * layer = lv_event_get_layer(e);
|
||||
|
||||
lv_point_t bg_pivot;
|
||||
lv_point_t pivot_px;
|
||||
lv_image_get_pivot(obj, &pivot_px);
|
||||
if(img->src_type == LV_IMAGE_SRC_FILE || img->src_type == LV_IMAGE_SRC_VARIABLE) {
|
||||
lv_draw_image_dsc_t draw_dsc;
|
||||
lv_draw_image_dsc_init(&draw_dsc);
|
||||
lv_obj_init_draw_image_dsc(obj, LV_PART_MAIN, &draw_dsc);
|
||||
|
||||
bg_pivot.x = pivot_px.x + pleft;
|
||||
bg_pivot.y = pivot_px.y + ptop;
|
||||
lv_area_t bg_coords;
|
||||
lv_area_t clip_area_ori = layer->clip_area;
|
||||
|
||||
if(img->obj_size_mode == LV_IMAGE_SIZE_MODE_REAL) {
|
||||
/*Object size equals to transformed image size*/
|
||||
lv_obj_get_coords(obj, &bg_coords);
|
||||
lv_image_get_pivot(obj, &draw_dsc.pivot);
|
||||
draw_dsc.scale_x = img->scale_x;
|
||||
draw_dsc.scale_y = img->scale_y;
|
||||
draw_dsc.rotation = img->rotation;
|
||||
draw_dsc.antialias = img->antialias;
|
||||
draw_dsc.src = img->src;
|
||||
|
||||
lv_area_t img_area = {obj->coords.x1, obj->coords.y1,
|
||||
obj->coords.x1 + img->w - 1, obj->coords.y1 + img->h - 1
|
||||
};
|
||||
if(img->align < _LV_IMAGE_ALIGN_AUTO_TRANSFORM) {
|
||||
lv_area_align(&obj->coords, &img_area, img->align, img->offset.x, img->offset.y);
|
||||
}
|
||||
else if(img->align == LV_IMAGE_ALIGN_TILE) {
|
||||
_lv_area_intersect(&layer->clip_area, &layer->clip_area, &obj->coords);
|
||||
lv_area_move(&img_area, img->offset.x, img->offset.y);
|
||||
|
||||
lv_area_move(&img_area,
|
||||
((layer->clip_area.x1 - img_area.x1 - (img->w - 1)) / img->w) * img->w,
|
||||
((layer->clip_area.y1 - img_area.y1 - (img->h - 1)) / img->h) * img->h);
|
||||
draw_dsc.tile = 1;
|
||||
}
|
||||
|
||||
lv_draw_image(layer, &draw_dsc, &img_area);
|
||||
layer->clip_area = clip_area_ori;
|
||||
|
||||
}
|
||||
else if(img->src_type == LV_IMAGE_SRC_SYMBOL) {
|
||||
lv_draw_label_dsc_t label_dsc;
|
||||
lv_draw_label_dsc_init(&label_dsc);
|
||||
lv_obj_init_draw_label_dsc(obj, LV_PART_MAIN, &label_dsc);
|
||||
label_dsc.text = img->src;
|
||||
lv_draw_label(layer, &label_dsc, &obj->coords);
|
||||
}
|
||||
else if(img->src == NULL) {
|
||||
/*Do not need to draw image when src is NULL*/
|
||||
LV_LOG_WARN("image source is NULL");
|
||||
}
|
||||
else {
|
||||
_lv_image_buf_get_transformed_area(&bg_coords, obj_w, obj_h,
|
||||
img->rotation, img->scale_x, img->scale_y, &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);
|
||||
lv_area_copy(&obj->coords, &bg_coords);
|
||||
|
||||
lv_result_t res = lv_obj_event_base(MY_CLASS, e);
|
||||
if(res != LV_RESULT_OK) return;
|
||||
|
||||
lv_area_copy(&obj->coords, &ori_coords);
|
||||
|
||||
if(code == LV_EVENT_DRAW_MAIN) {
|
||||
if(img->h == 0 || img->w == 0) return;
|
||||
if(img->scale_x == 0 || img->scale_y == 0) return;
|
||||
|
||||
lv_layer_t * layer = lv_event_get_layer(e);
|
||||
|
||||
lv_area_t img_max_area;
|
||||
lv_area_copy(&img_max_area, &obj->coords);
|
||||
|
||||
lv_point_t img_size_final = lv_image_get_transformed_size(obj);
|
||||
|
||||
if(img->obj_size_mode == LV_IMAGE_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;
|
||||
img_max_area.y2 -= pbottom;
|
||||
|
||||
if(img->src_type == LV_IMAGE_SRC_FILE || img->src_type == LV_IMAGE_SRC_VARIABLE) {
|
||||
lv_draw_image_dsc_t img_dsc;
|
||||
lv_draw_image_dsc_init(&img_dsc);
|
||||
lv_obj_init_draw_image_dsc(obj, LV_PART_MAIN, &img_dsc);
|
||||
|
||||
img_dsc.scale_x = img->scale_x;
|
||||
img_dsc.scale_y = img->scale_y;
|
||||
img_dsc.rotation = img->rotation;
|
||||
img_dsc.pivot.x = pivot_px.x;
|
||||
img_dsc.pivot.y = pivot_px.y;
|
||||
img_dsc.antialias = img->antialias;
|
||||
img_dsc.src = img->src;
|
||||
|
||||
lv_area_t img_clip_area;
|
||||
img_clip_area.x1 = bg_coords.x1 + pleft;
|
||||
img_clip_area.y1 = bg_coords.y1 + ptop;
|
||||
img_clip_area.x2 = bg_coords.x2 - pright;
|
||||
img_clip_area.y2 = bg_coords.y2 - pbottom;
|
||||
const lv_area_t clip_area_ori = layer->clip_area;
|
||||
|
||||
if(!_lv_area_intersect(&img_clip_area, &layer->clip_area, &img_clip_area)) return;
|
||||
layer->clip_area = img_clip_area;
|
||||
|
||||
lv_area_t coords_tmp;
|
||||
int32_t offset_x = img->offset.x % img->w;
|
||||
int32_t offset_y = img->offset.y % img->h;
|
||||
coords_tmp.y1 = img_max_area.y1 + offset_y;
|
||||
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_size_final.y, coords_tmp.y2 += img_size_final.y) {
|
||||
coords_tmp.x1 = img_max_area.x1 + 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_size_final.x, coords_tmp.x2 += img_size_final.x) {
|
||||
lv_draw_image(layer, &img_dsc, &coords_tmp);
|
||||
}
|
||||
}
|
||||
layer->clip_area = clip_area_ori;
|
||||
}
|
||||
else if(img->src_type == LV_IMAGE_SRC_SYMBOL) {
|
||||
lv_draw_label_dsc_t label_dsc;
|
||||
lv_draw_label_dsc_init(&label_dsc);
|
||||
lv_obj_init_draw_label_dsc(obj, LV_PART_MAIN, &label_dsc);
|
||||
label_dsc.text = img->src;
|
||||
lv_draw_label(layer, &label_dsc, &obj->coords);
|
||||
}
|
||||
else if(img->src == NULL) {
|
||||
/*Do not need to draw image when src is NULL*/
|
||||
LV_LOG_WARN("image source is NULL");
|
||||
}
|
||||
else {
|
||||
/*Trigger the error handler of image draw*/
|
||||
LV_LOG_WARN("image source type is unknown");
|
||||
}
|
||||
/*Trigger the error handler of image draw*/
|
||||
LV_LOG_WARN("image source type is unknown");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -793,13 +715,6 @@ static void scale_update(lv_obj_t * obj, int32_t scale_x, int32_t scale_y)
|
||||
{
|
||||
lv_image_t * img = (lv_image_t *)obj;
|
||||
|
||||
if(img->obj_size_mode == LV_IMAGE_SIZE_MODE_REAL) {
|
||||
img->scale_x = scale_x;
|
||||
img->scale_y = scale_y;
|
||||
lv_obj_invalidate_area(obj, &obj->coords);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/
|
||||
int32_t w = lv_obj_get_width(obj);
|
||||
int32_t h = lv_obj_get_height(obj);
|
||||
@ -829,7 +744,24 @@ static void scale_update(lv_obj_t * obj, int32_t scale_x, int32_t scale_y)
|
||||
a.x2 += obj->coords.x1 + 1;
|
||||
a.y2 += obj->coords.y1 + 1;
|
||||
lv_obj_invalidate_area(obj, &a);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void update_align(lv_obj_t * obj)
|
||||
{
|
||||
lv_image_t * img = (lv_image_t *)obj;
|
||||
if(img->align == LV_IMAGE_ALIGN_STRETCH) {
|
||||
lv_image_set_rotation(obj, 0);
|
||||
lv_image_set_pivot(obj, 0, 0);
|
||||
int32_t scale_x = lv_obj_get_width(obj) * LV_SCALE_NONE / img->w;
|
||||
int32_t scale_y = lv_obj_get_height(obj) * LV_SCALE_NONE / img->h;
|
||||
scale_update(obj, scale_x, scale_y);
|
||||
}
|
||||
else if(img->align == LV_IMAGE_ALIGN_TILE) {
|
||||
lv_image_set_rotation(obj, 0);
|
||||
lv_image_set_pivot(obj, 0, 0);
|
||||
scale_update(obj, LV_SCALE_NONE, LV_SCALE_NONE);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -39,18 +39,18 @@ extern "C" {
|
||||
*/
|
||||
typedef struct {
|
||||
lv_obj_t obj;
|
||||
const void * src; /*Image source: Pointer to an array or a file or a symbol*/
|
||||
const void * src; /**< Image source: Pointer to an array or a file or a symbol*/
|
||||
lv_point_t offset;
|
||||
int32_t w; /*Width of the image (Handled by the library)*/
|
||||
int32_t h; /*Height of the image (Handled by the library)*/
|
||||
uint32_t rotation; /*rotation angle of the image*/
|
||||
uint32_t scale_x; /*256 means no zoom, 512 double size, 128 half size*/
|
||||
uint32_t scale_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`*/
|
||||
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.*/
|
||||
int32_t w; /**< Width of the image (Handled by the library)*/
|
||||
int32_t h; /**< Height of the image (Handled by the library)*/
|
||||
uint32_t rotation; /**< Rotation angle of the image*/
|
||||
uint32_t scale_x; /**< 256 means no zoom, 512 double size, 128 half size*/
|
||||
uint32_t scale_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`*/
|
||||
uint8_t antialias : 1; /**< Apply anti-aliasing in transformations (rotate, zoom)*/
|
||||
uint8_t align: 4; /**< Image size mode when image size and object size is different. See `lv_image_align_t`*/
|
||||
} lv_image_t;
|
||||
|
||||
LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_image_class;
|
||||
@ -58,22 +58,26 @@ LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_image_class;
|
||||
/**
|
||||
* Image size mode, when image size and object size is different
|
||||
*/
|
||||
enum _lv_image_size_mode_t {
|
||||
/** 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_IMAGE_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 image will be cropped when zoomed in.*/
|
||||
LV_IMAGE_SIZE_MODE_REAL,
|
||||
enum _lv_image_align_t {
|
||||
LV_IMAGE_ALIGN_DEFAULT = 0,
|
||||
LV_IMAGE_ALIGN_TOP_LEFT,
|
||||
LV_IMAGE_ALIGN_TOP_MID,
|
||||
LV_IMAGE_ALIGN_TOP_RIGHT,
|
||||
LV_IMAGE_ALIGN_BOTTOM_LEFT,
|
||||
LV_IMAGE_ALIGN_BOTTOM_MID,
|
||||
LV_IMAGE_ALIGN_BOTTOM_RIGHT,
|
||||
LV_IMAGE_ALIGN_LEFT_MID,
|
||||
LV_IMAGE_ALIGN_RIGHT_MID,
|
||||
LV_IMAGE_ALIGN_CENTER,
|
||||
_LV_IMAGE_ALIGN_AUTO_TRANSFORM,
|
||||
LV_IMAGE_ALIGN_STRETCH,
|
||||
LV_IMAGE_ALIGN_TILE,
|
||||
};
|
||||
|
||||
#ifdef DOXYGEN
|
||||
typedef _lv_image_size_mode_t lv_image_size_mode_t;
|
||||
typedef _lv_image_align_t lv_image_align_t;
|
||||
#else
|
||||
typedef uint8_t lv_image_size_mode_t;
|
||||
typedef uint8_t lv_image_align_t;
|
||||
#endif /*DOXYGEN*/
|
||||
|
||||
#if LV_USE_OBJ_PROPERTY
|
||||
@ -85,7 +89,7 @@ enum {
|
||||
LV_PROPERTY_ID(IMAGE, PIVOT, LV_PROPERTY_TYPE_POINTER, 4),
|
||||
LV_PROPERTY_ID(IMAGE, SCALE, LV_PROPERTY_TYPE_INT, 5),
|
||||
LV_PROPERTY_ID(IMAGE, ANTIALIAS, LV_PROPERTY_TYPE_INT, 6),
|
||||
LV_PROPERTY_ID(IMAGE, SIZE_MODE, LV_PROPERTY_TYPE_INT, 7),
|
||||
LV_PROPERTY_ID(IMAGE, ALIGN, LV_PROPERTY_TYPE_INT, 7),
|
||||
LV_PROPERTY_IMAGE_END,
|
||||
};
|
||||
#endif
|
||||
@ -135,7 +139,10 @@ void lv_image_set_offset_y(lv_obj_t * obj, int32_t y);
|
||||
* The image will be rotated around the set pivot set by `lv_image_set_pivot()`
|
||||
* Note that indexed and alpha only images can't be transformed.
|
||||
* @param obj pointer to an image object
|
||||
* @param angle rotation in degree with 0.1 degree resolution (0..3600: clock wise)
|
||||
* @param angle rotation in degree with 0.1 degree resolution (0..3600: clock wise)
|
||||
* @note if image_align is `LV_IMAGE_ALIGN_STRETCH` or `LV_IMAGE_ALIGN_FIT`
|
||||
* rotation will be set to 0 automatically.
|
||||
*
|
||||
*/
|
||||
void lv_image_set_rotation(lv_obj_t * obj, int32_t angle);
|
||||
|
||||
@ -208,11 +215,13 @@ void lv_image_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.
|
||||
* @param align the new align mode.
|
||||
* @note if image_align is `LV_IMAGE_ALIGN_STRETCH` or `LV_IMAGE_ALIGN_FIT`
|
||||
* rotation, scale and pivot will be overwritten and controlled internally.
|
||||
*/
|
||||
void lv_image_set_size_mode(lv_obj_t * obj, lv_image_size_mode_t mode);
|
||||
void lv_image_set_align(lv_obj_t * obj, lv_image_align_t align);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@ -241,7 +250,9 @@ int32_t lv_image_get_offset_y(lv_obj_t * obj);
|
||||
/**
|
||||
* Get the rotation of the image.
|
||||
* @param obj pointer to an image object
|
||||
* @return rotation in 0.1 degrees (0..3600)
|
||||
* @return rotation in 0.1 degrees (0..3600)
|
||||
* @note if image_align is `LV_IMAGE_ALIGN_STRETCH` or `LV_IMAGE_ALIGN_FIT`
|
||||
* rotation will be set to 0 automatically.
|
||||
*/
|
||||
int32_t lv_image_get_rotation(lv_obj_t * obj);
|
||||
|
||||
@ -284,9 +295,9 @@ bool lv_image_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_image_size_mode_t
|
||||
* @return element of @ref lv_image_align_t
|
||||
*/
|
||||
lv_image_size_mode_t lv_image_get_size_mode(lv_obj_t * obj);
|
||||
lv_image_align_t lv_image_get_align(lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
|
BIN
tests/ref_imgs/image_normal_align.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
tests/ref_imgs/image_normal_align_offset.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
tests/ref_imgs/image_rotate_and_scale_pivot_center.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
tests/ref_imgs/image_rotate_and_scale_pivot_top_left.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
tests/ref_imgs/image_rotate_pivot_center.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
tests/ref_imgs/image_rotate_pivot_top_left.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
tests/ref_imgs/image_scale_pivot_center.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
tests/ref_imgs/image_scale_pivot_top_left.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
tests/ref_imgs/image_scale_x_pivot_center.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
tests/ref_imgs/image_scale_x_pivot_top_left.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
tests/ref_imgs/image_scale_y_pivot_center.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
tests/ref_imgs/image_scale_y_pivot_top_left.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
tests/ref_imgs/image_stretch.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
tests/ref_imgs/image_tile.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
tests/ref_imgs/image_transform_align.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
tests/ref_imgs/image_transform_align_offset.png
Normal file
After Width: | Height: | Size: 17 KiB |
367
tests/src/test_cases/test_image.c
Normal file
@ -0,0 +1,367 @@
|
||||
#if LV_BUILD_TEST || 1
|
||||
#include "../lvgl.h"
|
||||
|
||||
#include "unity/unity.h"
|
||||
|
||||
LV_IMAGE_DECLARE(test_img_lvgl_logo_png);
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
/* Function run after every test */
|
||||
lv_obj_clean(lv_screen_active());
|
||||
}
|
||||
|
||||
static lv_obj_t * img_create(void)
|
||||
{
|
||||
lv_obj_t * img = lv_image_create(lv_screen_active());
|
||||
lv_image_set_src(img, &test_img_lvgl_logo_png);
|
||||
lv_obj_set_style_bg_opa(img, LV_OPA_20, 0);
|
||||
lv_obj_set_style_shadow_width(img, 10, 0);
|
||||
lv_obj_set_style_shadow_color(img, lv_color_hex(0xff0000), 0);
|
||||
return img;
|
||||
}
|
||||
|
||||
void test_image_rotated_pivot_center(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
for(i = 0; i < 8; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_pos(img, 100 + (i % 4) * 160, 150 + (i / 4) * 150);
|
||||
lv_image_set_rotation(img, i * 450);
|
||||
/*The default pivot should be the center*/
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_rotate_pivot_center.png");
|
||||
}
|
||||
|
||||
void test_image_rotated_pivot_top_left(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
for(i = 0; i < 8; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_pos(img, 120 + (i % 4) * 180, 100 + (i / 4) * 300);
|
||||
lv_image_set_rotation(img, i * 450);
|
||||
lv_image_set_pivot(img, 0, 0);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_rotate_pivot_top_left.png");
|
||||
}
|
||||
|
||||
void test_image_scale_pivot_center(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
for(i = 0; i < 8; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_pos(img, 40 + (i % 4) * 200, 150 + (i / 4) * 150);
|
||||
lv_image_set_scale(img, 64 + i * 64);
|
||||
/*The default pivot should be the center*/
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_scale_pivot_center.png");
|
||||
}
|
||||
|
||||
void test_image_scale_pivot_top_left(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
for(i = 0; i < 8; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_pos(img, 10 + (i % 4) * 190, 150 + (i / 4) * 150);
|
||||
lv_image_set_scale(img, 64 + i * 64);
|
||||
lv_image_set_pivot(img, 0, 0);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_scale_pivot_top_left.png");
|
||||
}
|
||||
|
||||
void test_image_scale_x_pivot_center(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
for(i = 0; i < 8; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_pos(img, 40 + (i % 4) * 200, 150 + (i / 4) * 150);
|
||||
lv_image_set_scale_x(img, 64 + i * 64);
|
||||
/*The default pivot should be the center*/
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_scale_x_pivot_center.png");
|
||||
}
|
||||
|
||||
void test_image_scale_x_pivot_top_left(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
for(i = 0; i < 8; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_pos(img, 10 + (i % 4) * 190, 150 + (i / 4) * 150);
|
||||
lv_image_set_scale_x(img, 64 + i * 64);
|
||||
lv_image_set_pivot(img, 0, 0);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_scale_x_pivot_top_left.png");
|
||||
}
|
||||
|
||||
void test_image_scale_y_pivot_center(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
for(i = 0; i < 8; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_pos(img, 40 + (i % 4) * 200, 150 + (i / 4) * 150);
|
||||
lv_image_set_scale_y(img, 64 + i * 64);
|
||||
/*The default pivot should be the center*/
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_scale_y_pivot_center.png");
|
||||
}
|
||||
|
||||
void test_image_scale_y_pivot_top_left(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
for(i = 0; i < 8; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_pos(img, 10 + (i % 4) * 190, 150 + (i / 4) * 150);
|
||||
lv_image_set_scale_y(img, 64 + i * 64);
|
||||
lv_image_set_pivot(img, 0, 0);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_scale_y_pivot_top_left.png");
|
||||
}
|
||||
|
||||
void test_image_rotate_and_scale_pivot_center(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
for(i = 0; i < 8; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_pos(img, 40 + (i % 4) * 200, 150 + (i / 4) * 150);
|
||||
lv_image_set_scale_x(img, 64 + i * 64);
|
||||
lv_image_set_scale_y(img, 32 + i * 96);
|
||||
lv_image_set_rotation(img, 200 + i * 333);
|
||||
/*The default pivot should be the center*/
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_rotate_and_scale_pivot_center.png");
|
||||
}
|
||||
|
||||
void test_image_rotate_and_scale_pivot_top_left(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
for(i = 0; i < 8; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_pos(img, 120 + (i % 4) * 180, 120 + (i / 4) * 220);
|
||||
lv_image_set_scale_x(img, 64 + i * 64);
|
||||
lv_image_set_scale_y(img, 32 + i * 96);
|
||||
lv_image_set_rotation(img, 200 + i * 333);
|
||||
lv_image_set_pivot(img, 0, 0);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_rotate_and_scale_pivot_top_left.png");
|
||||
}
|
||||
|
||||
void test_image_normal_align(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
lv_image_align_t aligns[] = {
|
||||
LV_IMAGE_ALIGN_TOP_LEFT, LV_IMAGE_ALIGN_TOP_MID, LV_IMAGE_ALIGN_TOP_RIGHT,
|
||||
LV_IMAGE_ALIGN_LEFT_MID, LV_IMAGE_ALIGN_CENTER, LV_IMAGE_ALIGN_RIGHT_MID,
|
||||
LV_IMAGE_ALIGN_BOTTOM_LEFT, LV_IMAGE_ALIGN_BOTTOM_MID, LV_IMAGE_ALIGN_BOTTOM_RIGHT,
|
||||
};
|
||||
|
||||
for(i = 0; i < 9; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_size(img, 200, 120);
|
||||
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
|
||||
lv_image_set_align(img, aligns[i]);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_normal_align.png");
|
||||
}
|
||||
|
||||
void test_image_normal_align_offset(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
lv_image_align_t aligns[] = {
|
||||
LV_IMAGE_ALIGN_TOP_LEFT, LV_IMAGE_ALIGN_TOP_MID, LV_IMAGE_ALIGN_TOP_RIGHT,
|
||||
LV_IMAGE_ALIGN_LEFT_MID, LV_IMAGE_ALIGN_CENTER, LV_IMAGE_ALIGN_RIGHT_MID,
|
||||
LV_IMAGE_ALIGN_BOTTOM_LEFT, LV_IMAGE_ALIGN_BOTTOM_MID, LV_IMAGE_ALIGN_BOTTOM_RIGHT,
|
||||
};
|
||||
|
||||
for(i = 0; i < 9; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_size(img, 200, 120);
|
||||
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
|
||||
lv_image_set_align(img, aligns[i]);
|
||||
lv_image_set_offset_x(img, 15);
|
||||
lv_image_set_offset_y(img, 20);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_normal_align_offset.png");
|
||||
}
|
||||
|
||||
void test_image_transform_align(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
lv_image_align_t aligns[] = {
|
||||
LV_IMAGE_ALIGN_TOP_LEFT, LV_IMAGE_ALIGN_TOP_MID, LV_IMAGE_ALIGN_TOP_RIGHT,
|
||||
LV_IMAGE_ALIGN_LEFT_MID, LV_IMAGE_ALIGN_CENTER, LV_IMAGE_ALIGN_RIGHT_MID,
|
||||
LV_IMAGE_ALIGN_BOTTOM_LEFT, LV_IMAGE_ALIGN_BOTTOM_MID, LV_IMAGE_ALIGN_BOTTOM_RIGHT,
|
||||
};
|
||||
|
||||
for(i = 0; i < 9; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_size(img, 200, 120);
|
||||
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
|
||||
lv_image_set_scale_x(img, 300);
|
||||
lv_image_set_scale_y(img, 200);
|
||||
lv_image_set_rotation(img, 200);
|
||||
lv_image_set_align(img, aligns[i]);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_transform_align.png");
|
||||
}
|
||||
|
||||
void test_image_transform_align_offset(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
lv_image_align_t aligns[] = {
|
||||
LV_IMAGE_ALIGN_TOP_LEFT, LV_IMAGE_ALIGN_TOP_MID, LV_IMAGE_ALIGN_TOP_RIGHT,
|
||||
LV_IMAGE_ALIGN_LEFT_MID, LV_IMAGE_ALIGN_CENTER, LV_IMAGE_ALIGN_RIGHT_MID,
|
||||
LV_IMAGE_ALIGN_BOTTOM_LEFT, LV_IMAGE_ALIGN_BOTTOM_MID, LV_IMAGE_ALIGN_BOTTOM_RIGHT,
|
||||
};
|
||||
|
||||
for(i = 0; i < 9; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_size(img, 200, 120);
|
||||
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
|
||||
lv_image_set_align(img, aligns[i]);
|
||||
lv_image_set_offset_x(img, 15);
|
||||
lv_image_set_offset_y(img, 20);
|
||||
lv_image_set_scale_x(img, 300);
|
||||
lv_image_set_scale_y(img, 200);
|
||||
lv_image_set_rotation(img, 200);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_transform_align_offset.png");
|
||||
}
|
||||
|
||||
void test_image_stretch(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
uint32_t i;
|
||||
|
||||
int32_t img_w = test_img_lvgl_logo_png.header.w;
|
||||
int32_t img_h = test_img_lvgl_logo_png.header.h;
|
||||
|
||||
int32_t w_array[] = {img_w / 2, img_w, img_w * 2};
|
||||
int32_t h_array[] = {img_h / 2, img_h, img_h * 2};
|
||||
|
||||
|
||||
for(i = 0; i < 9; i++) {
|
||||
img = img_create();
|
||||
lv_obj_set_size(img, w_array[i / 3], h_array[i % 3]);
|
||||
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
|
||||
lv_image_set_align(img, LV_IMAGE_ALIGN_STRETCH);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_stretch.png");
|
||||
}
|
||||
|
||||
|
||||
void test_image_tile(void)
|
||||
{
|
||||
lv_obj_t * img;
|
||||
|
||||
img = img_create();
|
||||
lv_obj_set_size(img, 350, LV_SIZE_CONTENT);
|
||||
lv_image_set_align(img, LV_IMAGE_ALIGN_TILE);
|
||||
lv_obj_set_pos(img, 20, 20);
|
||||
img = img_create();
|
||||
|
||||
lv_obj_set_size(img, LV_SIZE_CONTENT, 150);
|
||||
lv_image_set_align(img, LV_IMAGE_ALIGN_TILE);
|
||||
lv_obj_set_pos(img, 420, 20);
|
||||
|
||||
img = img_create();
|
||||
lv_obj_set_size(img, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
|
||||
lv_image_set_align(img, LV_IMAGE_ALIGN_TILE);
|
||||
lv_obj_set_pos(img, 20, 220);
|
||||
lv_image_set_offset_x(img, -20);
|
||||
lv_image_set_offset_y(img, 20);
|
||||
|
||||
img = img_create();
|
||||
lv_obj_set_size(img, 150, 150);
|
||||
lv_image_set_align(img, LV_IMAGE_ALIGN_TILE);
|
||||
lv_obj_set_pos(img, 220, 220);
|
||||
|
||||
img = img_create();
|
||||
lv_obj_set_size(img, 150, 150);
|
||||
lv_image_set_align(img, LV_IMAGE_ALIGN_TILE);
|
||||
lv_obj_set_pos(img, 420, 220);
|
||||
lv_image_set_offset_x(img, -2000);
|
||||
lv_image_set_offset_y(img, 2000);
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("image_tile.png");
|
||||
}
|
||||
|
||||
void test_image_ignore_transformation_settings_when_stretched(void)
|
||||
{
|
||||
lv_obj_t * img = img_create();
|
||||
lv_obj_set_size(img, 200, 300);
|
||||
lv_image_set_align(img, LV_IMAGE_ALIGN_STRETCH);
|
||||
|
||||
lv_image_set_rotation(img, 100);
|
||||
lv_image_set_pivot(img, 200, 300);
|
||||
TEST_ASSERT_EQUAL_INT(0, lv_image_get_rotation(img));
|
||||
|
||||
lv_point_t pivot;
|
||||
lv_image_get_pivot(img, &pivot);
|
||||
TEST_ASSERT_EQUAL_INT(0, pivot.x);
|
||||
TEST_ASSERT_EQUAL_INT(0, pivot.y);
|
||||
|
||||
int32_t scale_x_original = lv_image_get_scale_x(img);
|
||||
int32_t scale_y_original = lv_image_get_scale_y(img);
|
||||
lv_image_set_scale_x(img, 400);
|
||||
lv_image_set_scale_y(img, 500);
|
||||
TEST_ASSERT_EQUAL_INT(scale_x_original, lv_image_get_scale_x(img));
|
||||
TEST_ASSERT_EQUAL_INT(scale_y_original, lv_image_get_scale_y(img));
|
||||
}
|
||||
|
||||
void test_image_ignore_transformation_settings_when_tiled(void)
|
||||
{
|
||||
lv_obj_t * img = img_create();
|
||||
lv_obj_set_size(img, 200, 300);
|
||||
lv_image_set_align(img, LV_IMAGE_ALIGN_TILE);
|
||||
|
||||
lv_image_set_rotation(img, 100);
|
||||
lv_image_set_pivot(img, 200, 300);
|
||||
lv_image_set_scale_x(img, 400);
|
||||
lv_image_set_scale_y(img, 500);
|
||||
|
||||
lv_point_t pivot;
|
||||
lv_image_get_pivot(img, &pivot);
|
||||
TEST_ASSERT_EQUAL_INT(0, pivot.x);
|
||||
TEST_ASSERT_EQUAL_INT(0, pivot.y);
|
||||
TEST_ASSERT_EQUAL_INT(0, lv_image_get_rotation(img));
|
||||
TEST_ASSERT_EQUAL_INT(LV_SCALE_NONE, lv_image_get_scale_x(img));
|
||||
TEST_ASSERT_EQUAL_INT(LV_SCALE_NONE, lv_image_get_scale_y(img));
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|