mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
Merge branch 'dev-7.0' of https://github.com/littlevgl/lvgl into dev-7.0
This commit is contained in:
commit
75f27bbeae
127
a.txt
Normal file
127
a.txt
Normal file
@ -0,0 +1,127 @@
|
||||
diff --git a/src/lv_draw/lv_draw_img.c b/src/lv_draw/lv_draw_img.c
|
||||
index f28c47eb..74f73686 100644
|
||||
--- a/src/lv_draw/lv_draw_img.c
|
||||
+++ b/src/lv_draw/lv_draw_img.c
|
||||
@@ -406,7 +406,7 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
trans_dsc.cfg.pivot_x = map_w / 2;
|
||||
trans_dsc.cfg.pivot_y = map_h / 2;
|
||||
trans_dsc.cfg.color = style->image.color;
|
||||
- trans_dsc.cfg.antialias = antialaias;
|
||||
+ trans_dsc.cfg.antialias = true;
|
||||
|
||||
lv_img_buf_transform_init(&trans_dsc);
|
||||
}
|
||||
diff --git a/src/lv_draw/lv_img_buf.c b/src/lv_draw/lv_img_buf.c
|
||||
index 2b79c7b1..89a57708 100644
|
||||
--- a/src/lv_draw/lv_img_buf.c
|
||||
+++ b/src/lv_draw/lv_img_buf.c
|
||||
@@ -161,6 +161,68 @@ lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y)
|
||||
return LV_OPA_COVER;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * 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)
|
||||
+{
|
||||
+ uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
+
|
||||
+ if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
+ uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
+ uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
+ memcpy(&buf_u8[px], &c, px_size);
|
||||
+ } else if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
+ uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
+ uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
+ memcpy(&buf_u8[px], &c, px_size - 1); /*-1 to not overwrite the alpha value*/
|
||||
+ } else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) {
|
||||
+ buf_u8 += sizeof(lv_color32_t) * 2; /*Skip the palette*/
|
||||
+
|
||||
+ uint8_t bit = x & 0x7;
|
||||
+ x = x >> 3;
|
||||
+
|
||||
+ /* Get the current pixel.
|
||||
+ * dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
+ * so the possible real width are 8 ,16, 24 ...*/
|
||||
+ uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
+ buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
|
||||
+ buf_u8[px] = buf_u8[px] | ((c.full & 0x1) << (7 - bit));
|
||||
+ } else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) {
|
||||
+ buf_u8 += sizeof(lv_color32_t) * 4; /*Skip the palette*/
|
||||
+ uint8_t bit = (x & 0x3) * 2;
|
||||
+ x = x >> 2;
|
||||
+
|
||||
+ /* Get the current pixel.
|
||||
+ * dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned
|
||||
+ * so the possible real width are 4, 8 ,12 ...*/
|
||||
+ uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
+
|
||||
+ buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
|
||||
+ buf_u8[px] = buf_u8[px] | ((c.full & 0x3) << (6 - bit));
|
||||
+ } else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) {
|
||||
+ buf_u8 += sizeof(lv_color32_t) * 16; /*Skip the palette*/
|
||||
+ uint8_t bit = (x & 0x1) * 4;
|
||||
+ x = x >> 1;
|
||||
+
|
||||
+ /* Get the current pixel.
|
||||
+ * dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned
|
||||
+ * so the possible real width are 2 ,4, 6 ...*/
|
||||
+ uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
+ buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
|
||||
+ buf_u8[px] = buf_u8[px] | ((c.full & 0xF) << (4 - bit));
|
||||
+ } else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
+ buf_u8 += sizeof(lv_color32_t) * 256; /*Skip the palette*/
|
||||
+ uint32_t px = dsc->header.w * y + x;
|
||||
+ buf_u8[px] = c.full;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* Set the alpha value of a pixel of an image. The color won't be affected
|
||||
* @param dsc pointer to an image descriptor
|
||||
diff --git a/src/lv_draw/lv_img_buf.h b/src/lv_draw/lv_img_buf.h
|
||||
index 2629b465..3c1d8273 100644
|
||||
--- a/src/lv_draw/lv_img_buf.h
|
||||
+++ b/src/lv_draw/lv_img_buf.h
|
||||
@@ -205,6 +205,7 @@ lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t
|
||||
*/
|
||||
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
|
||||
diff --git a/src/lv_objx/lv_img.c b/src/lv_objx/lv_img.c
|
||||
index 982bb8d9..f792867a 100644
|
||||
--- a/src/lv_objx/lv_img.c
|
||||
+++ b/src/lv_objx/lv_img.c
|
||||
@@ -273,7 +273,6 @@ void lv_img_set_angle(lv_obj_t * img, int16_t angle)
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
if(angle == ext->angle) return;
|
||||
|
||||
- lv_obj_invalidate(img);
|
||||
ext->angle = angle;
|
||||
lv_obj_refresh_ext_draw_pad(img);
|
||||
lv_obj_invalidate(img);
|
||||
@@ -296,7 +295,6 @@ void lv_img_set_zoom(lv_obj_t * img, uint16_t zoom)
|
||||
|
||||
if(zoom == 0) zoom = 1;
|
||||
|
||||
- lv_obj_invalidate(img);
|
||||
ext->zoom = zoom;
|
||||
lv_obj_refresh_ext_draw_pad(img);
|
||||
lv_obj_invalidate(img);
|
||||
@@ -533,7 +531,7 @@ static lv_res_t lv_img_signal(lv_obj_t * img, lv_signal_t sign, void * param)
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) {
|
||||
/*If the image has angle provide enough room for the rotated corners */
|
||||
- if(ext->angle || ext->zoom != LV_IMG_ZOOM_NONE) {
|
||||
+ if(ext->angle && ext->zoom) {
|
||||
lv_sqrt_res_t ds;
|
||||
lv_sqrt(ext->w * ext->w + ext->h * ext->h, &ds);
|
||||
ds.i = (ds.i * ext->zoom + 0) >> 8; /*+10 to be sure anything won't be clipped*/
|
@ -8,6 +8,7 @@
|
||||
*********************/
|
||||
#include "lv_draw_arc.h"
|
||||
#include "lv_draw_mask.h"
|
||||
#include "../lv_misc/lv_math.h" // LV_TRIGO_SHIFT
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -70,7 +71,32 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
|
||||
lv_draw_mask_remove_id(mask_angle_id);
|
||||
|
||||
if(style->line.rounded) {
|
||||
/*TODO*/
|
||||
circle_style.body.main_color = style->line.color;
|
||||
circle_style.body.grad_color = style->line.color;
|
||||
circle_style.body.opa = LV_OPA_COVER;
|
||||
circle_style.body.border.width = 0;
|
||||
|
||||
lv_coord_t thick_half = style->line.width / 2;
|
||||
lv_coord_t cir_x = ((radius - thick_half + 1) * lv_trigo_sin(90 - start_angle) >> LV_TRIGO_SHIFT);
|
||||
lv_coord_t cir_y = ((radius - thick_half + 1) * lv_trigo_sin(start_angle) >> LV_TRIGO_SHIFT);
|
||||
|
||||
lv_area_t round_area;
|
||||
round_area.x1 = cir_x + center_x - thick_half + 1;
|
||||
round_area.y1 = cir_y + center_y - thick_half + 1;
|
||||
round_area.x2 = cir_x + center_x + thick_half;
|
||||
round_area.y2 = cir_y + center_y + thick_half;
|
||||
|
||||
lv_draw_rect(&round_area, clip_area, &circle_style, LV_OPA_COVER);
|
||||
|
||||
cir_x = ((radius - thick_half + 1) * lv_trigo_sin(90 - end_angle) >> LV_TRIGO_SHIFT);
|
||||
cir_y = ((radius - thick_half + 1) * lv_trigo_sin(end_angle) >> LV_TRIGO_SHIFT);
|
||||
|
||||
round_area.x1 = cir_x + center_x - thick_half + 1;
|
||||
round_area.y1 = cir_y + center_y - thick_half + 1;
|
||||
round_area.x2 = cir_x + center_x + thick_half;
|
||||
round_area.y2 = cir_y + center_y + thick_half;
|
||||
|
||||
lv_draw_rect(&round_area, clip_area, &circle_style, LV_OPA_COVER);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -573,13 +573,9 @@ static void map_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, cons
|
||||
const lv_opa_t * mask_tmp = mask - draw_area->x1;
|
||||
|
||||
/*Buffer the result color to avoid recalculating the same color*/
|
||||
lv_color_t last_dest_color;
|
||||
lv_color_t last_map_color;
|
||||
lv_color_t last_res_color;
|
||||
lv_color_t res_color;
|
||||
lv_opa_t last_mask = LV_OPA_TRANSP;
|
||||
last_dest_color.full = disp_buf_tmp[0].full;
|
||||
last_map_color.full = disp_buf_tmp[0].full;
|
||||
last_res_color.full = disp_buf_tmp[0].full;
|
||||
res_color.full = disp_buf_tmp[0].full;
|
||||
|
||||
/*Only the mask matters*/
|
||||
if(opa > LV_OPA_MAX) {
|
||||
@ -589,19 +585,18 @@ static void map_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, cons
|
||||
|
||||
for(y = draw_area->y1; y <= draw_area->y2; y++) {
|
||||
for(x = draw_area->x1; x <= draw_area->x2; x++) {
|
||||
if(mask_tmp[x] == 0) continue;
|
||||
if(mask_tmp[x] < LV_OPA_MIN) continue;
|
||||
#if LV_COLOR_SCREEN_TRANSP
|
||||
if(disp->driver.screen_transp) {
|
||||
lv_color_mix_with_alpha(disp_buf_tmp[x], disp_buf_tmp[x].ch.alpha, map_buf_tmp[x], mask_tmp[x], &last_res_color, &opa_composed);
|
||||
last_res_color.ch.alpha = opa_composed;
|
||||
lv_color_mix_with_alpha(disp_buf_tmp[x], disp_buf_tmp[x].ch.alpha, map_buf_tmp[x], mask_tmp[x], &res_color, &opa_composed);
|
||||
res_color.ch.alpha = opa_composed;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if(mask_tmp[x] > LV_OPA_MAX) last_res_color = map_buf_tmp[x];
|
||||
else if(mask_tmp[x] < LV_OPA_MIN) last_res_color = disp_buf_tmp[x];
|
||||
else last_res_color = lv_color_mix(map_buf_tmp[x], disp_buf_tmp[x], mask_tmp[x]);
|
||||
if(mask_tmp[x] > LV_OPA_MAX) res_color = map_buf_tmp[x];
|
||||
else res_color = lv_color_mix(map_buf_tmp[x], disp_buf_tmp[x], mask_tmp[x]);
|
||||
}
|
||||
disp_buf_tmp[x] = last_res_color;//lv_color_mix(map_buf_tmp[x], disp_buf_tmp[x], mask_tmp[x]);
|
||||
disp_buf_tmp[x] = res_color;//lv_color_mix(map_buf_tmp[x], disp_buf_tmp[x], mask_tmp[x]);
|
||||
}
|
||||
disp_buf_tmp += disp_w;
|
||||
mask_tmp += draw_area_w;
|
||||
|
@ -26,10 +26,10 @@
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mask, const void * src,
|
||||
const lv_style_t * style, uint16_t angle, lv_opa_t opa_scale);
|
||||
const lv_style_t * style, uint16_t angle, uint16_t zoom, bool antialaias, lv_opa_t opa_scale);
|
||||
|
||||
static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, const uint8_t * map_p, lv_opa_t opa,
|
||||
bool chroma_key, bool alpha_byte, const lv_style_t * style, uint16_t angle);
|
||||
bool chroma_key, bool alpha_byte, const lv_style_t * style, uint16_t angle, uint16_t zoom, bool antialaias);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@ -49,10 +49,11 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
* @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 style style of the image
|
||||
* @param antialias anti-alias transformations (rotate, zoom) or not
|
||||
* @param opa_scale scale down all opacities by the factor
|
||||
*/
|
||||
void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * src, const lv_style_t * style,
|
||||
uint16_t angle, lv_opa_t opa_scale)
|
||||
uint16_t angle, uint16_t zoom, bool antialias, lv_opa_t opa_scale)
|
||||
{
|
||||
if(src == NULL) {
|
||||
LV_LOG_WARN("Image draw: src is NULL");
|
||||
@ -62,7 +63,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void *
|
||||
}
|
||||
|
||||
lv_res_t res;
|
||||
res = lv_img_draw_core(coords, mask, src, style, angle, opa_scale);
|
||||
res = lv_img_draw_core(coords, mask, src, style, angle, zoom, antialias, opa_scale);
|
||||
|
||||
if(res == LV_RES_INV) {
|
||||
LV_LOG_WARN("Image draw error");
|
||||
@ -189,7 +190,7 @@ lv_img_src_t lv_img_src_get_type(const void * src)
|
||||
**********************/
|
||||
|
||||
static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mask, const void * src,
|
||||
const lv_style_t * style, uint16_t angle, lv_opa_t opa_scale)
|
||||
const lv_style_t * style, uint16_t angle, uint16_t zoom, bool antialias, lv_opa_t opa_scale)
|
||||
{
|
||||
lv_opa_t opa =
|
||||
opa_scale == LV_OPA_COVER ? style->image.opa : (uint16_t)((uint16_t)style->image.opa * opa_scale) >> 8;
|
||||
@ -211,16 +212,21 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas
|
||||
else if(cdsc->dec_dsc.img_data) {
|
||||
lv_area_t map_area_rot;
|
||||
lv_area_copy(&map_area_rot, coords);
|
||||
if(angle) {
|
||||
if(angle || zoom != LV_IMG_ZOOM_NONE) {
|
||||
/*Get the exact area which is required to show the rotated image*/
|
||||
lv_coord_t pivot_x = lv_area_get_width(coords) / 2 + coords->x1;
|
||||
lv_coord_t pivot_y = lv_area_get_height(coords) / 2 + coords->y1;
|
||||
|
||||
lv_coord_t w = lv_area_get_width(coords);
|
||||
lv_coord_t w_zoom = (((w * zoom) >> 8) - w) / 2;
|
||||
lv_coord_t h = lv_area_get_height(coords);
|
||||
lv_coord_t h_zoom = (((h * zoom) >> 8) - h) / 2;
|
||||
|
||||
lv_area_t norm;
|
||||
norm.x1 = + coords->x1 - pivot_x;
|
||||
norm.y1 = + coords->y1 - pivot_y;
|
||||
norm.x2 = + coords->x2 - pivot_x;
|
||||
norm.y2 = + coords->y2 - pivot_y;
|
||||
norm.x1 = coords->x1 - pivot_x - w_zoom;
|
||||
norm.y1 = coords->y1 - pivot_y - h_zoom;
|
||||
norm.x2 = coords->x2 - pivot_x + w_zoom;
|
||||
norm.y2 = coords->y2 - pivot_y + h_zoom;
|
||||
|
||||
int16_t sinma = lv_trigo_sin(-angle);
|
||||
int16_t cosma = lv_trigo_sin(-angle + 90);
|
||||
@ -255,7 +261,7 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas
|
||||
successfully.*/
|
||||
}
|
||||
|
||||
lv_draw_map(coords, &mask_com, cdsc->dec_dsc.img_data, opa, chroma_keyed, alpha_byte, style, angle);
|
||||
lv_draw_map(coords, &mask_com, cdsc->dec_dsc.img_data, opa, chroma_keyed, alpha_byte, style, angle, zoom, antialias);
|
||||
}
|
||||
/* The whole uncompressed image is not available. Try to read it line-by-line*/
|
||||
else {
|
||||
@ -292,7 +298,7 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas
|
||||
}
|
||||
|
||||
|
||||
lv_draw_map(&line, &mask_line, buf, opa, chroma_keyed, alpha_byte, style, 0);
|
||||
lv_draw_map(&line, &mask_line, buf, opa, chroma_keyed, alpha_byte, style, 0, LV_IMG_ZOOM_NONE, false);
|
||||
line.y1++;
|
||||
line.y2++;
|
||||
y++;
|
||||
@ -312,9 +318,12 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas
|
||||
* @param chroma_keyed true: enable transparency of LV_IMG_LV_COLOR_TRANSP color pixels
|
||||
* @param alpha_byte true: extra alpha byte is inserted for every pixel
|
||||
* @param style style of the image
|
||||
* @param angle angle in degree
|
||||
* @param zoom zoom factor
|
||||
* @param antialias anti-alias transformations (rotate, zoom) or not
|
||||
*/
|
||||
static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, const uint8_t * map_p, lv_opa_t opa,
|
||||
bool chroma_key, bool alpha_byte, const lv_style_t * style, uint16_t angle)
|
||||
bool chroma_key, bool alpha_byte, const lv_style_t * style, uint16_t angle, uint16_t zoom, bool antialaias)
|
||||
{
|
||||
|
||||
if(opa < LV_OPA_MIN) return;
|
||||
@ -338,8 +347,10 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
uint8_t other_mask_cnt = lv_draw_mask_get_cnt();
|
||||
|
||||
/*The simplest case just copy the pixels into the VDB*/
|
||||
if(other_mask_cnt == 0 && angle == 0 && chroma_key == false && alpha_byte == false && style->image.intense == LV_OPA_TRANSP) {
|
||||
lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, style->image.blend_mode);
|
||||
if(other_mask_cnt == 0 && angle == 0 && zoom == LV_IMG_ZOOM_NONE &&
|
||||
chroma_key == false && alpha_byte == false &&
|
||||
opa == LV_OPA_COVER && style->image.intense == LV_OPA_TRANSP) {
|
||||
lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, LV_OPA_COVER, style->image.blend_mode);
|
||||
}
|
||||
/*In the other cases every pixel need to be checked one-by-one*/
|
||||
else {
|
||||
@ -377,14 +388,30 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
}
|
||||
|
||||
|
||||
lv_img_rotate_dsc_t rotate_dsc;
|
||||
memset(&rotate_dsc, 0, sizeof(lv_img_rotate_dsc_t));
|
||||
if(angle) {
|
||||
bool transform = angle != 0 || zoom != LV_IMG_ZOOM_NONE ? true : false;
|
||||
lv_img_transform_dsc_t trans_dsc;
|
||||
memset(&trans_dsc, 0, sizeof(lv_img_transform_dsc_t));
|
||||
if(transform) {
|
||||
lv_img_cf_t cf = LV_IMG_CF_TRUE_COLOR;
|
||||
if(alpha_byte) cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
|
||||
else if(chroma_key) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED;
|
||||
lv_img_buf_rotate_init(&rotate_dsc, angle, map_p, map_w, map_h, cf, map_w/2, map_h / 2, LV_COLOR_BLACK);
|
||||
|
||||
|
||||
trans_dsc.cfg.angle = angle;
|
||||
trans_dsc.cfg.zoom = zoom;
|
||||
trans_dsc.cfg.src = map_p;
|
||||
trans_dsc.cfg.src_w = map_w;
|
||||
trans_dsc.cfg.src_h = map_h;
|
||||
trans_dsc.cfg.cf = cf;
|
||||
trans_dsc.cfg.pivot_x = map_w / 2;
|
||||
trans_dsc.cfg.pivot_y = map_h / 2;
|
||||
trans_dsc.cfg.color = style->image.color;
|
||||
trans_dsc.cfg.antialias = antialaias;
|
||||
|
||||
lv_img_buf_transform_init(&trans_dsc);
|
||||
}
|
||||
|
||||
|
||||
lv_draw_mask_res_t mask_res;
|
||||
mask_res = (alpha_byte || chroma_key || angle) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
|
||||
lv_coord_t x;
|
||||
@ -395,7 +422,7 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
|
||||
for(x = 0; x < lv_area_get_width(&draw_area); x++, map_px += px_size_byte, px_i++) {
|
||||
|
||||
if(angle == 0) {
|
||||
if(transform == false) {
|
||||
if(alpha_byte) {
|
||||
lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1];
|
||||
mask_buf[px_i] = px_opa;
|
||||
@ -422,13 +449,13 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
bool ret;
|
||||
lv_coord_t rot_x = x + (disp_area->x1 + draw_area.x1) - map_area->x1;
|
||||
lv_coord_t rot_y = y + (disp_area->y1 + draw_area.y1) - map_area->y1;
|
||||
ret = lv_img_buf_get_px_rotated(&rotate_dsc, rot_x, rot_y);
|
||||
ret = lv_img_buf_transform(&trans_dsc, rot_x, rot_y);
|
||||
if(ret == false) {
|
||||
mask_buf[px_i] = LV_OPA_TRANSP;
|
||||
continue;
|
||||
} else {
|
||||
mask_buf[px_i] = rotate_dsc.res_opa;
|
||||
c.full = rotate_dsc.res_color.full;
|
||||
mask_buf[px_i] = trans_dsc.res.opa;
|
||||
c.full = trans_dsc.res.color.full;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,10 +40,11 @@ extern "C" {
|
||||
* @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 style style of the image
|
||||
* @param antialias anti-alias transformations (rotate, zoom) or not
|
||||
* @param opa_scale scale down all opacities by the factor
|
||||
*/
|
||||
void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * src, const lv_style_t * style,
|
||||
uint16_t angle, lv_opa_t opa_scale);
|
||||
uint16_t angle, uint16_t zoom, bool antialaias, lv_opa_t opa_scale);
|
||||
|
||||
/**
|
||||
* Get the type of an image source
|
||||
|
@ -24,6 +24,7 @@
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static inline bool transform_anti_alias(lv_img_transform_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@ -37,6 +38,7 @@
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
/**
|
||||
* Get the color of an image's pixel
|
||||
* @param dsc an image descriptor
|
||||
@ -47,26 +49,8 @@
|
||||
* @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, bool safe)
|
||||
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)
|
||||
{
|
||||
if(safe) {
|
||||
if(x >= dsc->header.w) {
|
||||
x = dsc->header.w - 1;
|
||||
LV_LOG_WARN("lv_img_buf_get_px_color: x is too large");
|
||||
} else if(x < 0) {
|
||||
x = 0;
|
||||
LV_LOG_WARN("lv_img_buf_get_px_color: x is < 0");
|
||||
}
|
||||
|
||||
if(y >= dsc->header.h) {
|
||||
y = dsc->header.h - 1;
|
||||
LV_LOG_WARN("lv_img_buf_get_px_color: y is too large");
|
||||
} else if(y < 0) {
|
||||
y = 0;
|
||||
LV_LOG_WARN("lv_img_buf_get_px_color: y is < 0");
|
||||
}
|
||||
}
|
||||
|
||||
lv_color_t p_color = LV_COLOR_BLACK;
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
@ -114,7 +98,7 @@ lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t
|
||||
p_color.full = buf_u8[px];
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT ||
|
||||
dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
p_color = color;
|
||||
p_color = color;
|
||||
}
|
||||
return p_color;
|
||||
}
|
||||
@ -127,26 +111,8 @@ lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t
|
||||
* @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, bool safe)
|
||||
lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
if(safe) {
|
||||
if(x >= dsc->header.w) {
|
||||
x = dsc->header.w - 1;
|
||||
LV_LOG_WARN("lv_img_buf_get_px_alpha: x is too large");
|
||||
} else if(x < 0) {
|
||||
x = 0;
|
||||
LV_LOG_WARN("lv_img_buf_get_px_alpha: x is < 0");
|
||||
}
|
||||
|
||||
if(y >= dsc->header.h) {
|
||||
y = dsc->header.h - 1;
|
||||
LV_LOG_WARN("lv_img_buf_get_px_alpha: y is too large");
|
||||
} else if(y < 0) {
|
||||
y = 0;
|
||||
LV_LOG_WARN("lv_img_buf_get_px_alpha: y is < 0");
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
@ -195,6 +161,61 @@ lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
return LV_OPA_COVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
buf_u8[px + px_size - 1] = opa;
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) {
|
||||
opa = opa >> 7; /*opa -> [0,1]*/
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0x1) << (7 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) {
|
||||
opa = opa >> 6; /*opa -> [0,3]*/
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 4 ,8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0x3) << (6 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) {
|
||||
opa = opa >> 4; /*opa -> [0,15]*/
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0xF) << (4 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
buf_u8[px] = opa;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the color of a pixel of an image. The alpha channel won't be affected.
|
||||
* @param dsc pointer to an image descriptor
|
||||
@ -203,26 +224,8 @@ lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
* @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, bool safe)
|
||||
void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c)
|
||||
{
|
||||
if(safe) {
|
||||
if(x >= dsc->header.w) {
|
||||
x = dsc->header.w - 1;
|
||||
LV_LOG_WARN("lv_img_buf_set_px_color: x is too large");
|
||||
} else if(x < 0) {
|
||||
x = 0;
|
||||
LV_LOG_WARN("lv_img_buf_set_px_color: x is < 0");
|
||||
}
|
||||
|
||||
if(y >= dsc->header.h) {
|
||||
y = dsc->header.h - 1;
|
||||
LV_LOG_WARN("lv_img_buf_set_px_color: y is too large");
|
||||
} else if(y < 0) {
|
||||
y = 0;
|
||||
LV_LOG_WARN("lv_img_buf_set_px_color: y is < 0");
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
@ -275,79 +278,6 @@ void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, bool safe)
|
||||
{
|
||||
if(safe) {
|
||||
if(x >= dsc->header.w) {
|
||||
x = dsc->header.w - 1;
|
||||
LV_LOG_WARN("lv_img_buf_set_px_alpha: x is too large");
|
||||
} else if(x < 0) {
|
||||
x = 0;
|
||||
LV_LOG_WARN("lv_img_buf_set_px_alpha: x is < 0");
|
||||
}
|
||||
|
||||
if(y >= dsc->header.h) {
|
||||
y = dsc->header.h - 1;
|
||||
LV_LOG_WARN("lv_img_buf_set_px_alpha: y is too large");
|
||||
} else if(y < 0) {
|
||||
y = 0;
|
||||
LV_LOG_WARN("lv_img_buf_set_px_alpha: y is < 0");
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
buf_u8[px + px_size - 1] = opa;
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) {
|
||||
opa = opa >> 7; /*opa -> [0,1]*/
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0x1) << (7 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) {
|
||||
opa = opa >> 6; /*opa -> [0,3]*/
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 4 ,8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0x3) << (6 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) {
|
||||
opa = opa >> 4; /*opa -> [0,15]*/
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0xF) << (4 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
buf_u8[px] = 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
|
||||
@ -451,48 +381,33 @@ uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a descriptor to rotate an image
|
||||
* @param dsc pointer to an `lv_img_rotate_dsc_t` variable
|
||||
* @param angle angle to rotate
|
||||
* @param src image source (array of pixels)
|
||||
* @param src_w width of the image to rotate
|
||||
* @param src_h height of the image to rotate
|
||||
* @param cf color format of the image to rotate
|
||||
* @param pivot_x pivot x
|
||||
* @param pivot_y pivot y
|
||||
* @param color a color used for `LV_IMG_CF_INDEXED_1/2/4/8BIT` color formats
|
||||
* Initialize a descriptor to tranform an image
|
||||
* @param dsc pointer to an `lv_img_transform_dsc_t` variable whose `cfg` field is initialized
|
||||
*/
|
||||
void lv_img_buf_rotate_init(lv_img_rotate_dsc_t * dsc, int16_t angle, const void * src, lv_coord_t src_w, lv_coord_t src_h,
|
||||
lv_img_cf_t cf, lv_coord_t pivot_x, lv_coord_t pivot_y, lv_color_t color)
|
||||
void lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc)
|
||||
{
|
||||
memset(dsc, 0x00, sizeof(lv_img_rotate_dsc_t));
|
||||
dsc->tmp.pivot_x_256 = dsc->cfg.pivot_x * 256;
|
||||
dsc->tmp.pivot_y_256 = dsc->cfg.pivot_y * 256;
|
||||
dsc->tmp.sinma = lv_trigo_sin(-dsc->cfg.angle);
|
||||
dsc->tmp.cosma = lv_trigo_sin(-dsc->cfg.angle + 90);
|
||||
|
||||
dsc->angle = angle;
|
||||
dsc->src = src;
|
||||
dsc->src_w = src_w;
|
||||
dsc->src_h = src_h;
|
||||
dsc->cf = cf;
|
||||
dsc->color = color;
|
||||
dsc->pivot_x = pivot_x;
|
||||
dsc->pivot_y = pivot_y;
|
||||
dsc->pivot_x_256 = pivot_x * 256;
|
||||
dsc->pivot_y_256 = pivot_y * 256;
|
||||
dsc->sinma = lv_trigo_sin(-angle);
|
||||
dsc->cosma = lv_trigo_sin(-angle + 90);
|
||||
|
||||
dsc->chroma_keyed = lv_img_cf_is_chroma_keyed(cf) ? 1 : 0;
|
||||
dsc->has_alpha = lv_img_cf_has_alpha(cf) ? 1 : 0;
|
||||
if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_ALPHA || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
dsc->native_color = 1;
|
||||
dsc->tmp.chroma_keyed = lv_img_cf_is_chroma_keyed(dsc->cfg.cf) ? 1 : 0;
|
||||
dsc->tmp.has_alpha = lv_img_cf_has_alpha(dsc->cfg.cf) ? 1 : 0;
|
||||
if(dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR || dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR_ALPHA || dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
dsc->tmp.native_color = 1;
|
||||
}
|
||||
|
||||
dsc->img_dsc.data = src;
|
||||
dsc->img_dsc.header.always_zero = 0;
|
||||
dsc->img_dsc.header.cf = cf;
|
||||
dsc->img_dsc.header.w = src_w;
|
||||
dsc->img_dsc.header.h = src_h;
|
||||
dsc->tmp.img_dsc.data = dsc->cfg.src;
|
||||
dsc->tmp.img_dsc.header.always_zero = 0;
|
||||
dsc->tmp.img_dsc.header.cf = dsc->cfg.cf;
|
||||
dsc->tmp.img_dsc.header.w = dsc->cfg.src_w;
|
||||
dsc->tmp.img_dsc.header.h = dsc->cfg.src_h;
|
||||
|
||||
dsc->res_opa = LV_OPA_COVER;
|
||||
|
||||
dsc->tmp.zoom_inv = (256 * 256) / dsc->cfg.zoom;
|
||||
|
||||
dsc->res.opa = LV_OPA_COVER;
|
||||
dsc->res.color = dsc->cfg.color;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -503,166 +418,189 @@ void lv_img_buf_rotate_init(lv_img_rotate_dsc_t * dsc, int16_t angle, const void
|
||||
* @return true: there is valid pixel on these x/y coordinates; false: the rotated pixel was out of the image
|
||||
* @note the result is written back to `dsc->res_color` and `dsc->res_opa`
|
||||
*/
|
||||
bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord_t y)
|
||||
bool lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
const uint8_t * src_u8 = dsc->src;
|
||||
const uint8_t * src_u8 = dsc->cfg.src;
|
||||
|
||||
/*Get the target point relative coordinates to the pivot*/
|
||||
int32_t xt = x - dsc->pivot_x;
|
||||
int32_t yt = y - dsc->pivot_y;
|
||||
int32_t xt = x - dsc->cfg.pivot_x;
|
||||
int32_t yt = y - dsc->cfg.pivot_y;
|
||||
|
||||
/*Get the source pixel from the upscaled image*/
|
||||
int32_t xs = ((dsc->cosma * xt - dsc->sinma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->pivot_x_256;
|
||||
int32_t ys = ((dsc->sinma * xt + dsc->cosma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->pivot_y_256;
|
||||
int32_t xs;
|
||||
int32_t ys;
|
||||
if(dsc->cfg.zoom == LV_IMG_ZOOM_NONE) {
|
||||
/*Get the source pixel from the upscaled image*/
|
||||
xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_x_256;
|
||||
ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_y_256;
|
||||
} else {
|
||||
xt *= dsc->tmp.zoom_inv;
|
||||
yt *= dsc->tmp.zoom_inv;
|
||||
xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (LV_TRIGO_SHIFT)) + dsc->tmp.pivot_x_256;
|
||||
ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (LV_TRIGO_SHIFT)) + dsc->tmp.pivot_y_256;
|
||||
|
||||
}
|
||||
|
||||
/*Get the integer part of the source pixel*/
|
||||
int xs_int = xs >> 8;
|
||||
int ys_int = ys >> 8;
|
||||
|
||||
if(xs_int >= dsc->src_w) return false;
|
||||
if(xs_int >= dsc->cfg.src_w) return false;
|
||||
else if(xs_int < 0) return false;
|
||||
|
||||
if(ys_int >= dsc->src_h) return false;
|
||||
if(ys_int >= dsc->cfg.src_h) return false;
|
||||
else if(ys_int < 0) return false;
|
||||
|
||||
/*Get the fractional part of the source pixel*/
|
||||
int xs_fract = xs & 0xff;
|
||||
int ys_fract = ys & 0xff;
|
||||
|
||||
/* If the fractional < 0x70 mix the source pixel with the left/top pixel
|
||||
* If the fractional > 0x90 mix the source pixel with the right/bottom pixel
|
||||
* In the 0x70..0x90 range use the unchanged source pixel */
|
||||
|
||||
lv_color_t c_dest_int;
|
||||
lv_opa_t opa_dest_int = 0;
|
||||
|
||||
uint8_t px_size;
|
||||
uint32_t px;
|
||||
if(dsc->native_color) {
|
||||
if(dsc->has_alpha == 0) {
|
||||
uint32_t pxi;
|
||||
if(dsc->tmp.native_color) {
|
||||
if(dsc->tmp.has_alpha == 0) {
|
||||
px_size = LV_COLOR_SIZE >> 3;
|
||||
|
||||
px = dsc->src_w * ys_int * px_size + xs_int * px_size;
|
||||
memcpy(&c_dest_int, &src_u8[px], px_size);
|
||||
pxi = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size;
|
||||
memcpy(&dsc->res.color, &src_u8[pxi], px_size);
|
||||
} else {
|
||||
px_size = LV_IMG_PX_SIZE_ALPHA_BYTE;
|
||||
px = dsc->src_w * ys_int * px_size + xs_int * px_size;
|
||||
memcpy(&c_dest_int, &src_u8[px], px_size - 1);
|
||||
opa_dest_int = src_u8[px + px_size - 1];
|
||||
pxi = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size;
|
||||
memcpy(&dsc->res.color, &src_u8[pxi], px_size - 1);
|
||||
dsc->res.opa = src_u8[pxi + px_size - 1];
|
||||
}
|
||||
} else {
|
||||
px = 0; /*unused*/
|
||||
pxi = 0; /*unused*/
|
||||
px_size = 0; /*unused*/
|
||||
c_dest_int = lv_img_buf_get_px_color(&dsc->img_dsc, xs_int, ys_int, dsc->color, false);
|
||||
opa_dest_int = lv_img_buf_get_px_alpha(&dsc->img_dsc, xs_int, ys_int, false);
|
||||
dsc->res.color = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, xs_int, ys_int, dsc->cfg.color);
|
||||
dsc->res.opa = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, xs_int, ys_int);
|
||||
}
|
||||
|
||||
|
||||
if(dsc->chroma_keyed) {
|
||||
if(dsc->tmp.chroma_keyed) {
|
||||
lv_color_t ct = LV_COLOR_TRANSP;
|
||||
if(c_dest_int.full == ct.full) return false;
|
||||
}
|
||||
|
||||
/*Get the mixture of the original source and the neightboor pixels in both directions*/
|
||||
lv_color_t c_x_dest;
|
||||
lv_color_t c_y_dest;
|
||||
lv_opa_t opa_x_dest = 0;
|
||||
lv_opa_t opa_y_dest = 0;
|
||||
|
||||
int32_t xn; /*x neightboor*/
|
||||
lv_opa_t xr; /*x mix ratio*/
|
||||
lv_color_t c_dest_xn;
|
||||
lv_opa_t opa_dest_xn = 0;
|
||||
|
||||
if(xs_fract < 0x70) {
|
||||
xn = xs_int - 1;
|
||||
if(xn < 0) return false;
|
||||
|
||||
xr = xs_fract + 0x80;
|
||||
|
||||
if(dsc->native_color) {
|
||||
memcpy(&c_dest_xn, &src_u8[px - px_size], sizeof(lv_color_t));
|
||||
if(dsc->has_alpha) opa_dest_xn = src_u8[px - 1];
|
||||
} else {
|
||||
c_dest_xn = lv_img_buf_get_px_color(&dsc->img_dsc, xn, ys_int, dsc->color, false);
|
||||
if(dsc->has_alpha) opa_dest_xn = lv_img_buf_get_px_alpha(&dsc->img_dsc, xn, ys_int, false);
|
||||
}
|
||||
|
||||
c_x_dest = lv_color_mix(c_dest_int, c_dest_xn, xr);
|
||||
if(dsc->has_alpha) opa_x_dest = (opa_dest_int * xr + (opa_dest_xn * (255 - xr))) >> 8;
|
||||
|
||||
} else if(xs_fract > 0x90) {
|
||||
xn = xs_int + 1;
|
||||
if(xn >= dsc->src_w) return false;
|
||||
|
||||
xr = (0xFF - xs_fract) + 0x80;
|
||||
|
||||
if(dsc->native_color) {
|
||||
memcpy(&c_dest_xn, &src_u8[px + px_size], sizeof(lv_color_t));
|
||||
if(dsc->has_alpha) opa_dest_xn = src_u8[px + 2 * px_size - 1];
|
||||
} else {
|
||||
c_dest_xn = lv_img_buf_get_px_color(&dsc->img_dsc, xn, ys_int, dsc->color, false);
|
||||
if(dsc->has_alpha) opa_dest_xn = lv_img_buf_get_px_alpha(&dsc->img_dsc, xn, ys_int, false);
|
||||
}
|
||||
|
||||
c_x_dest = lv_color_mix(c_dest_int, c_dest_xn, xr);
|
||||
if(dsc->has_alpha) opa_x_dest = (opa_dest_int * xr + (opa_dest_xn * (255 - xr))) >> 8;
|
||||
|
||||
} else {
|
||||
c_x_dest.full = c_dest_int.full;
|
||||
opa_x_dest = opa_dest_int;
|
||||
if(dsc->res.color.full == ct.full) return false;
|
||||
}
|
||||
|
||||
|
||||
int32_t yn; /*x neightboor*/
|
||||
lv_opa_t yr; /*x mix ratio*/
|
||||
lv_color_t c_dest_yn;
|
||||
lv_opa_t opa_dest_yn = 0;
|
||||
if(dsc->cfg.antialias == false) return true;
|
||||
|
||||
if(ys_fract < 0x70) {
|
||||
yn = ys_int - 1;
|
||||
if(yn < 0) return false;
|
||||
dsc->tmp.xs = xs;
|
||||
dsc->tmp.ys = ys;
|
||||
dsc->tmp.xs_int = xs_int;
|
||||
dsc->tmp.ys_int = ys_int;
|
||||
dsc->tmp.pxi = pxi;
|
||||
dsc->tmp.px_size = px_size;
|
||||
|
||||
yr = ys_fract + 0x80;
|
||||
bool ret;
|
||||
|
||||
if(dsc->native_color) {
|
||||
memcpy(&c_dest_yn, &src_u8[px - px_size * dsc->src_w], sizeof(lv_color_t));
|
||||
if(dsc->has_alpha) opa_dest_yn = src_u8[px - px_size * dsc->src_w + px_size- 1];
|
||||
} else {
|
||||
c_dest_yn = lv_img_buf_get_px_color(&dsc->img_dsc, xs_int, yn, dsc->color, false);
|
||||
if(dsc->has_alpha) opa_dest_yn = lv_img_buf_get_px_alpha(&dsc->img_dsc, xs_int, yn, false);
|
||||
}
|
||||
ret = transform_anti_alias(dsc);
|
||||
|
||||
c_y_dest = lv_color_mix(c_dest_int, c_dest_yn, yr);
|
||||
if(dsc->has_alpha) opa_y_dest = (opa_dest_int * yr + (opa_dest_yn * (255 - yr))) >> 8;
|
||||
|
||||
} else if(ys_fract > 0x90) {
|
||||
yn = ys_int + 1;
|
||||
if(yn >= dsc->src_h) return false;
|
||||
|
||||
yr = (0xFF - ys_fract) + 0x80;
|
||||
|
||||
if(dsc->native_color) {
|
||||
memcpy(&c_dest_yn, &src_u8[px + px_size * dsc->src_w], sizeof(lv_color_t));
|
||||
if(dsc->has_alpha) opa_dest_yn = src_u8[px + px_size * dsc->src_w + 2 * px_size - 1];
|
||||
} else {
|
||||
c_dest_yn = lv_img_buf_get_px_color(&dsc->img_dsc, xs_int, yn, dsc->color, false);
|
||||
if(dsc->has_alpha) opa_dest_yn = lv_img_buf_get_px_alpha(&dsc->img_dsc, xs_int, yn, false);
|
||||
}
|
||||
|
||||
c_y_dest = lv_color_mix(c_dest_int, c_dest_yn, yr);
|
||||
if(dsc->has_alpha) opa_y_dest = (opa_dest_int * yr + (opa_dest_yn * (255 - yr))) >> 8;
|
||||
} else {
|
||||
c_y_dest.full = c_dest_int.full;
|
||||
opa_y_dest = opa_dest_int;
|
||||
}
|
||||
|
||||
dsc->res_color = lv_color_mix(c_x_dest, c_y_dest, LV_OPA_50);
|
||||
if(dsc->has_alpha) dsc->res_opa = (opa_x_dest + opa_y_dest) >> 1;
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
static inline bool transform_anti_alias(lv_img_transform_dsc_t * dsc)
|
||||
{
|
||||
const uint8_t * src_u8 = dsc->cfg.src;
|
||||
|
||||
/*Get the fractional part of the source pixel*/
|
||||
int xs_fract = dsc->tmp.xs & 0xff;
|
||||
int ys_fract = dsc->tmp.ys & 0xff;
|
||||
int32_t xn; /*x neightboor*/
|
||||
lv_opa_t xr; /*x mix ratio*/
|
||||
|
||||
if(xs_fract < 0x70) {
|
||||
xn = - 1;
|
||||
if(dsc->tmp.xs_int + xn < 0) return false;
|
||||
xr = xs_fract + 0x80;
|
||||
} else if(xs_fract > 0x90) {
|
||||
xn = 1;
|
||||
if(dsc->tmp.xs_int + xn >= dsc->cfg.src_w) return false;
|
||||
xr = (0xFF - xs_fract) + 0x80;
|
||||
} else {
|
||||
xn = 0;
|
||||
xr = 0xFF;
|
||||
}
|
||||
|
||||
int32_t yn; /*x neightboor*/
|
||||
lv_opa_t yr; /*x mix ratio*/
|
||||
|
||||
if(ys_fract < 0x70) {
|
||||
yn = - 1;
|
||||
if(dsc->tmp.ys_int + yn < 0) return false;
|
||||
|
||||
yr = ys_fract + 0x80;
|
||||
} else if(ys_fract > 0x90) {
|
||||
yn = 1;
|
||||
if(dsc->tmp.ys_int + yn >= dsc->cfg.src_h) return false;
|
||||
|
||||
yr = (0xFF - ys_fract) + 0x80;
|
||||
} else {
|
||||
yn = 0;
|
||||
yr = 0xFF;
|
||||
}
|
||||
|
||||
lv_color_t c00 = dsc->res.color;
|
||||
lv_color_t c01;
|
||||
lv_color_t c10;
|
||||
lv_color_t c11;
|
||||
|
||||
lv_opa_t a00 = dsc->res.opa;
|
||||
lv_opa_t a10;
|
||||
lv_opa_t a01;
|
||||
lv_opa_t a11;
|
||||
|
||||
if(dsc->tmp.native_color) {
|
||||
memcpy(&c01, &src_u8[dsc->tmp.pxi + dsc->tmp.px_size * xn], sizeof(lv_color_t));
|
||||
memcpy(&c10, &src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn], sizeof(lv_color_t));
|
||||
memcpy(&c11, &src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size * xn], sizeof(lv_color_t));
|
||||
if(dsc->tmp.has_alpha) {
|
||||
a10 = src_u8[dsc->tmp.pxi + dsc->tmp.px_size * xn + dsc->tmp.px_size - 1];
|
||||
a01 = src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size - 1];
|
||||
a11 = src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size * xn + dsc->tmp.px_size - 1];
|
||||
}
|
||||
} else {
|
||||
c01 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int, dsc->cfg.color);
|
||||
c10 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int, dsc->tmp.ys_int + yn, dsc->cfg.color);
|
||||
c11 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int + yn, dsc->cfg.color);
|
||||
|
||||
if(dsc->tmp.has_alpha) {
|
||||
a10 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int);
|
||||
a01 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int, dsc->tmp.ys_int + yn);
|
||||
a11 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int + yn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lv_opa_t a0;
|
||||
lv_opa_t a1;
|
||||
lv_opa_t xr0 = xr;
|
||||
lv_opa_t xr1 = xr;
|
||||
if(dsc->tmp.has_alpha) {
|
||||
a0 = (a00 * xr + (a10 * (255 - xr))) >> 8;
|
||||
a1 = (a01 * xr + (a11 * (255 - xr))) >> 8;
|
||||
dsc->res.opa = (a0 * yr + (a1 * (255 - yr))) >> 8;
|
||||
|
||||
|
||||
if(a0 <= LV_OPA_MIN && a1 <= LV_OPA_MIN) return false;
|
||||
if(a0 <= LV_OPA_MIN) yr = LV_OPA_TRANSP;
|
||||
if(a1 <= LV_OPA_MIN) yr = LV_OPA_COVER;
|
||||
if(a00 <= LV_OPA_MIN) xr0 = LV_OPA_TRANSP;
|
||||
if(a10 <= LV_OPA_MIN) xr0 = LV_OPA_COVER;
|
||||
if(a01 <= LV_OPA_MIN) xr1 = LV_OPA_TRANSP;
|
||||
if(a11 <= LV_OPA_MIN) xr1 = LV_OPA_COVER;
|
||||
|
||||
} else {
|
||||
xr0 = xr;
|
||||
xr1 = xr;
|
||||
dsc->res.opa = LV_OPA_COVER;
|
||||
}
|
||||
|
||||
lv_color_t c0 = lv_color_mix(c00, c01, xr0);
|
||||
lv_color_t c1 = lv_color_mix(c10, c11, xr1);
|
||||
|
||||
dsc->res.color = lv_color_mix(c0, c1, yr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -46,6 +46,8 @@ extern "C" {
|
||||
#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_IMG_ZOOM_NONE 256
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
@ -125,30 +127,48 @@ typedef struct
|
||||
const uint8_t * data;
|
||||
} lv_img_dsc_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
lv_color_t res_color;
|
||||
lv_opa_t res_opa;
|
||||
struct {
|
||||
const void * src; /*image source (array of pixels)*/
|
||||
lv_coord_t src_w; /*width of the image source*/
|
||||
lv_coord_t src_h; /*height of the image source*/
|
||||
lv_coord_t pivot_x; /*pivot x*/
|
||||
lv_coord_t pivot_y; /* pivot y*/
|
||||
int16_t angle; /*angle to rotate*/
|
||||
uint16_t zoom; /*256 no zoom, 128 half size, 512 double size*/
|
||||
lv_color_t color; /*a color used for `LV_IMG_CF_INDEXED_1/2/4/8BIT` color formats*/
|
||||
lv_img_cf_t cf; /*color format of the image to rotate*/
|
||||
bool antialias;
|
||||
}cfg;
|
||||
|
||||
const void * src;
|
||||
lv_coord_t src_w;
|
||||
lv_coord_t src_h;
|
||||
lv_coord_t pivot_x;
|
||||
lv_coord_t pivot_y;
|
||||
int32_t pivot_x_256;
|
||||
int32_t pivot_y_256;
|
||||
lv_img_dsc_t img_dsc;
|
||||
int32_t sinma;
|
||||
int32_t cosma;
|
||||
int16_t angle;
|
||||
lv_color_t color;
|
||||
lv_img_cf_t cf;
|
||||
struct {
|
||||
lv_color_t color;
|
||||
lv_opa_t opa;
|
||||
}res;
|
||||
|
||||
uint8_t chroma_keyed :1;
|
||||
uint8_t has_alpha :1;
|
||||
uint8_t native_color :1;
|
||||
|
||||
}lv_img_rotate_dsc_t;
|
||||
struct {
|
||||
lv_img_dsc_t img_dsc;
|
||||
int32_t pivot_x_256;
|
||||
int32_t pivot_y_256;
|
||||
int32_t sinma;
|
||||
int32_t cosma;
|
||||
|
||||
uint8_t chroma_keyed :1;
|
||||
uint8_t has_alpha :1;
|
||||
uint8_t native_color :1;
|
||||
|
||||
uint16_t zoom_inv;
|
||||
|
||||
/*Runtime data*/
|
||||
lv_coord_t xs;
|
||||
lv_coord_t ys;
|
||||
lv_coord_t xs_int;
|
||||
lv_coord_t ys_int;
|
||||
uint32_t pxi;
|
||||
uint8_t px_size;
|
||||
}tmp;
|
||||
}lv_img_transform_dsc_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
@ -173,7 +193,7 @@ lv_img_dsc_t *lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
|
||||
* @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, bool safe);
|
||||
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
|
||||
@ -183,7 +203,7 @@ lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t
|
||||
* @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, bool safe);
|
||||
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.
|
||||
@ -193,7 +213,7 @@ lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
* @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, bool safe);
|
||||
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
|
||||
@ -203,7 +223,7 @@ void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_
|
||||
* @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, bool safe);
|
||||
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`
|
||||
@ -232,20 +252,12 @@ void lv_img_buf_free(lv_img_dsc_t *dsc);
|
||||
*/
|
||||
uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a descriptor to rotate an image
|
||||
* @param dsc pointer to an `lv_img_rotate_dsc_t` variable
|
||||
* @param angle angle to rotate
|
||||
* @param src image source (array of pixels)
|
||||
* @param src_w width of the image to rotate
|
||||
* @param src_h height of the image to rotate
|
||||
* @param cf color format of the image to rotate
|
||||
* @param pivot_x pivot x
|
||||
* @param pivot_y pivot y
|
||||
* @param color a color used for `LV_IMG_CF_INDEXED_1/2/4/8BIT` color formats
|
||||
* @param dsc pointer to an `lv_img_transform_dsc_t` variable whose `cfg` field is initialized
|
||||
*/
|
||||
void lv_img_buf_rotate_init(lv_img_rotate_dsc_t * dsc, int16_t angle, const void * src, lv_coord_t src_w, lv_coord_t src_h,
|
||||
lv_img_cf_t cf, lv_coord_t pivot_x, lv_coord_t pivot_y, lv_color_t color);
|
||||
void lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Get which color and opa would come to a pixel if it were rotated
|
||||
@ -255,7 +267,7 @@ void lv_img_buf_rotate_init(lv_img_rotate_dsc_t * dsc, int16_t angle, const void
|
||||
* @return true: there is valid pixel on these x/y coordinates; false: the rotated pixel was out of the image
|
||||
* @note the result is written back to `dsc->res_color` and `dsc->res_opa`
|
||||
*/
|
||||
bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord_t y);
|
||||
bool lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
|
||||
/**********************
|
||||
|
@ -123,6 +123,7 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
|
||||
task_interrupter =
|
||||
LV_GC_ROOT(_lv_task_act); /*Check all tasks again from the highest priority */
|
||||
end_flag = false;
|
||||
if(task_deleted) task_interrupter = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -133,6 +134,7 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
|
||||
if(lv_task_exec(LV_GC_ROOT(_lv_task_act))) {
|
||||
task_interrupter = LV_GC_ROOT(_lv_task_act); /*Check all tasks again from the highest priority */
|
||||
end_flag = false;
|
||||
if(task_deleted) task_interrupter = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -239,37 +239,6 @@ static lv_design_res_t lv_arc_design(lv_obj_t * arc, const lv_area_t * clip_area
|
||||
lv_coord_t y = arc->coords.y1 + lv_obj_get_height(arc) / 2;
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(arc);
|
||||
lv_draw_arc(x, y, r, clip_area, ext->angle_start, ext->angle_end, style, opa_scale);
|
||||
|
||||
/*Draw circle on the ends if enabled */
|
||||
if(style->line.rounded) {
|
||||
lv_coord_t thick_half = style->line.width / 2;
|
||||
lv_coord_t cir_x = ((r - thick_half) * lv_trigo_sin(ext->angle_start) >> LV_TRIGO_SHIFT);
|
||||
lv_coord_t cir_y = ((r - thick_half) * lv_trigo_sin(ext->angle_start + 90) >> LV_TRIGO_SHIFT);
|
||||
|
||||
lv_style_t cir_style;
|
||||
lv_style_copy(&cir_style, &lv_style_plain);
|
||||
cir_style.body.grad_color = style->line.color;
|
||||
cir_style.body.main_color = cir_style.body.grad_color;
|
||||
cir_style.body.radius = LV_RADIUS_CIRCLE;
|
||||
lv_area_t cir_area;
|
||||
cir_area.x1 = cir_x + x - thick_half;
|
||||
cir_area.y1 = cir_y + y - thick_half;
|
||||
cir_area.x2 = cir_x + x + thick_half;
|
||||
cir_area.y2 = cir_y + y + thick_half;
|
||||
|
||||
lv_draw_rect(&cir_area, clip_area, &cir_style, opa_scale);
|
||||
|
||||
cir_x = ((r - thick_half) * lv_trigo_sin(ext->angle_end) >> LV_TRIGO_SHIFT);
|
||||
cir_y = ((r - thick_half) * lv_trigo_sin(ext->angle_end + 90) >> LV_TRIGO_SHIFT);
|
||||
|
||||
cir_area.x1 = cir_x + x - thick_half;
|
||||
cir_area.y1 = cir_y + y - thick_half;
|
||||
cir_area.x2 = cir_x + x + thick_half;
|
||||
cir_area.y2 = cir_y + y + thick_half;
|
||||
|
||||
lv_draw_rect(&cir_area, clip_area, &cir_style, opa_scale);
|
||||
}
|
||||
|
||||
}
|
||||
/*Post draw when the children are drawn*/
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
|
@ -159,7 +159,7 @@ void lv_canvas_set_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t
|
||||
|
||||
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
|
||||
|
||||
lv_img_buf_set_px_color(&ext->dsc, x, y, c, true);
|
||||
lv_img_buf_set_px_color(&ext->dsc, x, y, c);
|
||||
lv_obj_invalidate(canvas);
|
||||
}
|
||||
|
||||
@ -218,7 +218,7 @@ lv_color_t lv_canvas_get_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y)
|
||||
|
||||
if(style == NULL) style = &lv_style_scr;
|
||||
|
||||
return lv_img_buf_get_px_color(&ext->dsc, x, y, style->image.color, true);
|
||||
return lv_img_buf_get_px_color(&ext->dsc, x, y, style->image.color);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -292,20 +292,22 @@ void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t x, l
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate and image and store the result on a canvas.
|
||||
* Transform and image and store the result on a canvas.
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param img pointer to an image descriptor.
|
||||
* Can be the image descriptor of an other canvas too (`lv_canvas_get_img()`).
|
||||
* @param angle the angle of rotation (0..360);
|
||||
* @param zoom zoom factor (256 no zoom);
|
||||
* @param offset_x offset X to tell where to put the result data on destination canvas
|
||||
* @param offset_y offset X to tell where to put the result data on destination canvas
|
||||
* @param pivot_x pivot X of rotation. Relative to the source canvas
|
||||
* Set to `source width / 2` to rotate around the center
|
||||
* @param pivot_y pivot Y of rotation. Relative to the source canvas
|
||||
* Set to `source height / 2` to rotate around the center
|
||||
* @param antialias apply anti-aliasing during the transformation. Looks better but slower.
|
||||
*/
|
||||
void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_coord_t offset_x, lv_coord_t offset_y,
|
||||
int32_t pivot_x, int32_t pivot_y)
|
||||
void lv_canvas_transform(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, uint16_t zoom, lv_coord_t offset_x, lv_coord_t offset_y,
|
||||
int32_t pivot_x, int32_t pivot_y, bool antialias)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(img);
|
||||
@ -320,58 +322,68 @@ void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_c
|
||||
int32_t y;
|
||||
bool ret;
|
||||
|
||||
lv_img_rotate_dsc_t dsc;
|
||||
lv_img_buf_rotate_init(&dsc, angle, img->data, img->header.w, img->header.h, img->header.cf, pivot_x, pivot_y, style->image.color);
|
||||
lv_img_transform_dsc_t dsc;
|
||||
dsc.cfg.angle = angle;
|
||||
dsc.cfg.zoom = zoom;
|
||||
dsc.cfg.src = img->data;
|
||||
dsc.cfg.src_w = img->header.w;
|
||||
dsc.cfg.src_h = img->header.h;
|
||||
dsc.cfg.cf = img->header.cf;
|
||||
dsc.cfg.pivot_x = pivot_x;
|
||||
dsc.cfg.pivot_y = pivot_y;
|
||||
dsc.cfg.color = style->image.color;
|
||||
dsc.cfg.antialias = antialias;
|
||||
lv_img_buf_transform_init(&dsc);
|
||||
|
||||
for(x = -offset_x; x < dest_width - offset_x; x++) {
|
||||
for(y = -offset_y; y < dest_height - offset_y; y++) {
|
||||
for(y = -offset_y; y < dest_height - offset_y; y++) {
|
||||
for(x = -offset_x; x < dest_width - offset_x; x++) {
|
||||
|
||||
ret = lv_img_buf_get_px_rotated(&dsc, x, y);
|
||||
ret = lv_img_buf_transform(&dsc, x, y);
|
||||
|
||||
if(ret == false) continue;
|
||||
|
||||
if(x + offset_x >= 0 && x + offset_x < dest_width && y + offset_y >= 0 && y + offset_y < dest_height) {
|
||||
/*If the image has no alpha channel just simple set the result color on the canvas*/
|
||||
if(lv_img_cf_has_alpha(img->header.cf) == false) {
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color, false);
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res.color);
|
||||
} else {
|
||||
lv_color_t bg_color = lv_img_buf_get_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, style->image.color, false);
|
||||
lv_color_t bg_color = lv_img_buf_get_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, style->image.color);
|
||||
|
||||
/*If the canvas has no alpha but the image has mix the image's color with
|
||||
* canvas*/
|
||||
if(lv_img_cf_has_alpha(ext_dst->dsc.header.cf) == false) {
|
||||
if(dsc.res_opa < LV_OPA_MAX) dsc.res_color = lv_color_mix(dsc.res_color, bg_color, dsc.res_opa);
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color, false);
|
||||
if(dsc.res.opa < LV_OPA_MAX) dsc.res.color = lv_color_mix(dsc.res.color, bg_color, dsc.res.opa);
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res.color);
|
||||
}
|
||||
/*Both the image and canvas has alpha channel. Some extra calculation is
|
||||
required*/
|
||||
else {
|
||||
lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, false);
|
||||
lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y);
|
||||
/* Pick the foreground if it's fully opaque or the Background is fully
|
||||
* transparent*/
|
||||
if(dsc.res_opa >= LV_OPA_MAX || bg_opa <= LV_OPA_MIN) {
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color, false);
|
||||
lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_opa, false);
|
||||
if(dsc.res.opa >= LV_OPA_MAX || bg_opa <= LV_OPA_MIN) {
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res.color);
|
||||
lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res.opa);
|
||||
}
|
||||
/*Opaque background: use simple mix*/
|
||||
else if(bg_opa >= LV_OPA_MAX) {
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y,
|
||||
lv_color_mix(dsc.res_color, bg_color, dsc.res_opa), false);
|
||||
lv_color_mix(dsc.res.color, bg_color, dsc.res.opa));
|
||||
}
|
||||
/*Both colors have alpha. Expensive calculation need to be applied*/
|
||||
else {
|
||||
|
||||
/*Info:
|
||||
* https://en.wikipedia.org/wiki/Alpha_compositing#Analytical_derivation_of_the_over_operator*/
|
||||
lv_opa_t opa_res_2 = 255 - ((uint16_t)((uint16_t)(255 - dsc.res_opa) * (255 - bg_opa)) >> 8);
|
||||
lv_opa_t opa_res_2 = 255 - ((uint16_t)((uint16_t)(255 - dsc.res.opa) * (255 - bg_opa)) >> 8);
|
||||
if(opa_res_2 == 0) {
|
||||
opa_res_2 = 1; /*never happens, just to be sure*/
|
||||
}
|
||||
lv_opa_t ratio = (uint16_t)((uint16_t)dsc.res_opa * 255) / opa_res_2;
|
||||
lv_opa_t ratio = (uint16_t)((uint16_t)dsc.res.opa * 255) / opa_res_2;
|
||||
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y,
|
||||
lv_color_mix(dsc.res_color, bg_color, ratio), false);
|
||||
lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, opa_res_2, false);
|
||||
lv_color_mix(dsc.res.color, bg_color, ratio));
|
||||
lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, opa_res_2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -449,8 +461,8 @@ void lv_canvas_blur_hor(lv_obj_t * canvas, const lv_area_t * area, uint16_t r)
|
||||
x_safe = x < 0 ? 0 : x;
|
||||
x_safe = x_safe > ext->dsc.header.w - 1 ? ext->dsc.header.w - 1 : x_safe;
|
||||
|
||||
c = lv_img_buf_get_px_color(&line_img, x_safe, 0, style->image.color, false);
|
||||
if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0, false);
|
||||
c = lv_img_buf_get_px_color(&line_img, x_safe, 0, style->image.color);
|
||||
if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0);
|
||||
|
||||
rsum += c.ch.red;
|
||||
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP
|
||||
@ -479,14 +491,14 @@ void lv_canvas_blur_hor(lv_obj_t * canvas, const lv_area_t * area, uint16_t r)
|
||||
c.ch.blue = bsum / r;
|
||||
if(has_alpha) opa = asum / r;
|
||||
|
||||
lv_img_buf_set_px_color(&ext->dsc, x, y, c, false);
|
||||
lv_img_buf_set_px_color(&ext->dsc, x, y, c);
|
||||
}
|
||||
if(has_alpha) lv_img_buf_set_px_alpha(&ext->dsc, x, y, opa, false);
|
||||
if(has_alpha) lv_img_buf_set_px_alpha(&ext->dsc, x, y, opa);
|
||||
|
||||
x_safe = x - r_back;
|
||||
x_safe = x_safe < 0 ? 0 : x_safe;
|
||||
c = lv_img_buf_get_px_color(&line_img, x_safe, 0, style->image.color, false);
|
||||
if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0, false);
|
||||
c = lv_img_buf_get_px_color(&line_img, x_safe, 0, style->image.color);
|
||||
if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0);
|
||||
|
||||
rsum -= c.ch.red;
|
||||
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP
|
||||
@ -499,8 +511,8 @@ void lv_canvas_blur_hor(lv_obj_t * canvas, const lv_area_t * area, uint16_t r)
|
||||
|
||||
x_safe = x + 1 + r_front;
|
||||
x_safe = x_safe > ext->dsc.header.w - 1 ? ext->dsc.header.w - 1 : x_safe;
|
||||
c = lv_img_buf_get_px_color(&line_img, x_safe, 0, LV_COLOR_RED, false);
|
||||
if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0, false);
|
||||
c = lv_img_buf_get_px_color(&line_img, x_safe, 0, LV_COLOR_RED);
|
||||
if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0);
|
||||
|
||||
rsum += c.ch.red;
|
||||
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP
|
||||
@ -581,11 +593,11 @@ void lv_canvas_blur_ver(lv_obj_t * canvas, const lv_area_t * area, uint16_t r)
|
||||
y_safe = y < 0 ? 0 : y;
|
||||
y_safe = y_safe > ext->dsc.header.h - 1 ? ext->dsc.header.h - 1 : y_safe;
|
||||
|
||||
c = lv_img_buf_get_px_color(&ext->dsc, x, y_safe, style->image.color, false);
|
||||
if(has_alpha) opa = lv_img_buf_get_px_alpha(&ext->dsc, x, y_safe, false);
|
||||
c = lv_img_buf_get_px_color(&ext->dsc, x, y_safe, style->image.color);
|
||||
if(has_alpha) opa = lv_img_buf_get_px_alpha(&ext->dsc, x, y_safe);
|
||||
|
||||
lv_img_buf_set_px_color(&line_img, 0, y_safe, c, false);
|
||||
if(has_alpha) lv_img_buf_set_px_alpha(&line_img, 0, y_safe, opa, false);
|
||||
lv_img_buf_set_px_color(&line_img, 0, y_safe, c);
|
||||
if(has_alpha) lv_img_buf_set_px_alpha(&line_img, 0, y_safe, opa);
|
||||
|
||||
rsum += c.ch.red;
|
||||
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP
|
||||
@ -613,14 +625,14 @@ void lv_canvas_blur_ver(lv_obj_t * canvas, const lv_area_t * area, uint16_t r)
|
||||
c.ch.blue = bsum / r;
|
||||
if(has_alpha) opa = asum / r;
|
||||
|
||||
lv_img_buf_set_px_color(&ext->dsc, x, y, c, false);
|
||||
lv_img_buf_set_px_color(&ext->dsc, x, y, c);
|
||||
}
|
||||
if(has_alpha) lv_img_buf_set_px_alpha(&ext->dsc, x, y, opa, false);
|
||||
if(has_alpha) lv_img_buf_set_px_alpha(&ext->dsc, x, y, opa);
|
||||
|
||||
y_safe = y - r_back;
|
||||
y_safe = y_safe < 0 ? 0 : y_safe;
|
||||
c = lv_img_buf_get_px_color(&line_img, 0, y_safe, style->image.color, false);
|
||||
if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, 0, y_safe, false);
|
||||
c = lv_img_buf_get_px_color(&line_img, 0, y_safe, style->image.color);
|
||||
if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, 0, y_safe);
|
||||
|
||||
rsum -= c.ch.red;
|
||||
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP
|
||||
@ -634,11 +646,11 @@ void lv_canvas_blur_ver(lv_obj_t * canvas, const lv_area_t * area, uint16_t r)
|
||||
y_safe = y + 1 + r_front;
|
||||
y_safe = y_safe > ext->dsc.header.h - 1 ? ext->dsc.header.h - 1 : y_safe;
|
||||
|
||||
c = lv_img_buf_get_px_color(&ext->dsc, x, y_safe, style->image.color, false);
|
||||
if(has_alpha) opa = lv_img_buf_get_px_alpha(&ext->dsc, x, y_safe, false);
|
||||
c = lv_img_buf_get_px_color(&ext->dsc, x, y_safe, style->image.color);
|
||||
if(has_alpha) opa = lv_img_buf_get_px_alpha(&ext->dsc, x, y_safe);
|
||||
|
||||
lv_img_buf_set_px_color(&line_img, 0, y_safe, c, false);
|
||||
if(has_alpha) lv_img_buf_set_px_alpha(&line_img, 0, y_safe, opa, false);
|
||||
lv_img_buf_set_px_color(&line_img, 0, y_safe, c);
|
||||
if(has_alpha) lv_img_buf_set_px_alpha(&line_img, 0, y_safe, opa);
|
||||
|
||||
rsum += c.ch.red;
|
||||
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP
|
||||
@ -661,7 +673,7 @@ void lv_canvas_blur_ver(lv_obj_t * canvas, const lv_area_t * area, uint16_t r)
|
||||
* @param canvas pointer to a canvas
|
||||
* @param color the background color
|
||||
*/
|
||||
void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color)
|
||||
void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
|
||||
@ -671,7 +683,8 @@ void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color)
|
||||
uint32_t y;
|
||||
for(y = 0; y < dsc->header.h; y++) {
|
||||
for(x = 0; x < dsc->header.w; x++) {
|
||||
lv_img_buf_set_px_color(dsc, x, y, color, false);
|
||||
lv_img_buf_set_px_color(dsc, x, y, color);
|
||||
lv_img_buf_set_px_alpha(dsc, x, y, opa);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -872,7 +885,7 @@ void lv_canvas_draw_img(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, const voi
|
||||
lv_disp_t * refr_ori = lv_refr_get_disp_refreshing();
|
||||
lv_refr_set_disp_refreshing(&disp);
|
||||
|
||||
lv_draw_img(&coords, &mask, src, style, 0, LV_OPA_COVER);
|
||||
lv_draw_img(&coords, &mask, src, style, 0, LV_IMG_ZOOM_NONE, false, LV_OPA_COVER);
|
||||
|
||||
lv_refr_set_disp_refreshing(refr_ori);
|
||||
}
|
||||
@ -1194,11 +1207,11 @@ static void set_px_alpha_generic(lv_img_dsc_t * d, lv_coord_t x, lv_coord_t y, l
|
||||
|
||||
uint8_t br = lv_color_brightness(color);
|
||||
if(opa < LV_OPA_MAX) {
|
||||
uint8_t bg = lv_img_buf_get_px_alpha(d, x, y, false);
|
||||
uint8_t bg = lv_img_buf_get_px_alpha(d, x, y);
|
||||
br = (uint16_t)((uint16_t)br * opa + (bg * (255 - opa))) >> 8;
|
||||
}
|
||||
|
||||
lv_img_buf_set_px_alpha(d, x, y, br, false);
|
||||
lv_img_buf_set_px_alpha(d, x, y, br);
|
||||
}
|
||||
|
||||
|
||||
@ -1215,8 +1228,8 @@ static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_
|
||||
d.header.w = buf_w;
|
||||
d.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
|
||||
|
||||
lv_color_t bg_color = lv_img_buf_get_px_color(&d, x, y, LV_COLOR_BLACK, false);
|
||||
lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&d, x, y, false);
|
||||
lv_color_t bg_color = lv_img_buf_get_px_color(&d, x, y, LV_COLOR_BLACK);
|
||||
lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&d, x, y);
|
||||
|
||||
lv_opa_t res_opa;
|
||||
lv_color_t res_color;
|
||||
@ -1224,8 +1237,8 @@ static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_
|
||||
lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &res_opa);
|
||||
|
||||
|
||||
lv_img_buf_set_px_alpha(&d, x, y, res_opa, false);
|
||||
lv_img_buf_set_px_color(&d, x, y, res_color, false);
|
||||
lv_img_buf_set_px_alpha(&d, x, y, res_opa);
|
||||
lv_img_buf_set_px_color(&d, x, y, res_color);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -151,20 +151,22 @@ void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t x, l
|
||||
lv_coord_t h);
|
||||
|
||||
/**
|
||||
* Rotate and image and store the result on a canvas.
|
||||
* Transform and image and store the result on a canvas.
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param img pointer to an image descriptor.
|
||||
* Can be the image descriptor of an other canvas too (`lv_canvas_get_img()`).
|
||||
* @param angle the angle of rotation (0..360);
|
||||
* @param zoom zoom factor (256 no zoom);
|
||||
* @param offset_x offset X to tell where to put the result data on destination canvas
|
||||
* @param offset_y offset X to tell where to put the result data on destination canvas
|
||||
* @param pivot_x pivot X of rotation. Relative to the source canvas
|
||||
* Set to `source width / 2` to rotate around the center
|
||||
* @param pivot_y pivot Y of rotation. Relative to the source canvas
|
||||
* Set to `source height / 2` to rotate around the center
|
||||
* @param antialias apply anti-aliasing during the transformation. Looks better but slower.
|
||||
*/
|
||||
void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_coord_t offset_x, lv_coord_t offset_y,
|
||||
int32_t pivot_x, int32_t pivot_y);
|
||||
void lv_canvas_transform(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, uint16_t zoom, lv_coord_t offset_x, lv_coord_t offset_y,
|
||||
int32_t pivot_x, int32_t pivot_y, bool antialias);
|
||||
|
||||
|
||||
|
||||
@ -188,7 +190,7 @@ void lv_canvas_blur_ver(lv_obj_t * canvas, const lv_area_t * area, uint16_t r);
|
||||
* @param canvas pointer to a canvas
|
||||
* @param color the background color
|
||||
*/
|
||||
void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color);
|
||||
void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color, lv_opa_t opa);
|
||||
|
||||
/**
|
||||
* Draw a rectangle on the canvas
|
||||
|
@ -80,6 +80,8 @@ lv_obj_t * lv_img_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
ext->w = lv_obj_get_width(new_img);
|
||||
ext->h = lv_obj_get_height(new_img);
|
||||
ext->angle = 0;
|
||||
ext->zoom = LV_IMG_ZOOM_NONE;
|
||||
ext->antialias = LV_ANTIALIAS ? 1 : 0;
|
||||
ext->auto_size = 1;
|
||||
ext->offset.x = 0;
|
||||
ext->offset.y = 0;
|
||||
@ -269,10 +271,49 @@ void lv_img_set_angle(lv_obj_t * img, int16_t angle)
|
||||
if(angle < 0 || angle >= 360) angle = angle % 360;
|
||||
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
if(angle == ext->angle) return;
|
||||
|
||||
lv_obj_invalidate(img);
|
||||
ext->angle = angle;
|
||||
lv_obj_refresh_ext_draw_pad(img);
|
||||
lv_obj_invalidate(img);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the zoom factor of the image.
|
||||
* @param img pointer to an image object
|
||||
* @param zoom the zoom factor.
|
||||
* - 256 or LV_ZOOM_IMG_NONE for no zoom
|
||||
* - <256: scale down
|
||||
* - >256 scale up
|
||||
* - 128 half size
|
||||
* - 512 double size
|
||||
*/
|
||||
void lv_img_set_zoom(lv_obj_t * img, uint16_t zoom)
|
||||
{
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
if(zoom == ext->zoom) return;
|
||||
|
||||
if(zoom == 0) zoom = 1;
|
||||
|
||||
lv_obj_invalidate(img);
|
||||
ext->zoom = zoom;
|
||||
lv_obj_refresh_ext_draw_pad(img);
|
||||
lv_obj_invalidate(img);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable anti-aliasing for the transformations (rotate, zoom) or not
|
||||
* @param img pointer to an image object
|
||||
* @param antialias true: anti-aliased; false: not anti-aliased
|
||||
*/
|
||||
void lv_img_set_antialias(lv_obj_t * img, bool antialias)
|
||||
{
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
if(antialias == ext->antialias) return;
|
||||
|
||||
ext->antialias = antialias;
|
||||
lv_obj_invalidate(img);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
@ -366,6 +407,34 @@ uint16_t lv_img_get_angle(lv_obj_t * img)
|
||||
return ext->angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the zoom factor of the image.
|
||||
* @param img pointer to an image object
|
||||
* @return zoom factor (256: no zoom)
|
||||
*/
|
||||
uint16_t lv_img_get_zoom(lv_obj_t * img)
|
||||
{
|
||||
LV_ASSERT_OBJ(img, LV_OBJX_NAME);
|
||||
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
return ext->zoom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether the transformations (rotate, zoom) are anti-aliased or not
|
||||
* @param img pointer to an image object
|
||||
* @return true: anti-aliased; false: not anti-aliased
|
||||
*/
|
||||
bool lv_img_get_antialias(lv_obj_t * img)
|
||||
{
|
||||
LV_ASSERT_OBJ(img, LV_OBJX_NAME);
|
||||
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
return ext->antialias ? true : false;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@ -414,7 +483,7 @@ static lv_design_res_t lv_img_design(lv_obj_t * img, const lv_area_t * clip_area
|
||||
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) {
|
||||
lv_draw_img(&cords_tmp, clip_area, ext->src, style, ext->angle, opa_scale);
|
||||
lv_draw_img(&cords_tmp, clip_area, ext->src, style, ext->angle, ext->zoom, ext->antialias, opa_scale);
|
||||
}
|
||||
}
|
||||
} else if(ext->src_type == LV_IMG_SRC_SYMBOL) {
|
||||
@ -426,7 +495,7 @@ static lv_design_res_t lv_img_design(lv_obj_t * img, const lv_area_t * clip_area
|
||||
} else {
|
||||
/*Trigger the error handler of image drawer*/
|
||||
LV_LOG_WARN("lv_img_design: image source type is unknown");
|
||||
lv_draw_img(&img->coords, clip_area, NULL, style, 0, opa_scale);
|
||||
lv_draw_img(&img->coords, clip_area, NULL, style, 0, LV_IMG_ZOOM_NONE, false, opa_scale);
|
||||
}
|
||||
}
|
||||
|
||||
@ -464,9 +533,10 @@ static lv_res_t lv_img_signal(lv_obj_t * img, lv_signal_t sign, void * param)
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) {
|
||||
/*If the image has angle provide enough room for the rotated corners */
|
||||
if(ext->angle) {
|
||||
if(ext->angle || ext->zoom != LV_IMG_ZOOM_NONE) {
|
||||
lv_sqrt_res_t ds;
|
||||
lv_sqrt(ext->w * ext->w + ext->h * ext->h, &ds);
|
||||
ds.i = (ds.i * ext->zoom + 0) >> 8; /*+10 to be sure anything won't be clipped*/
|
||||
|
||||
lv_coord_t d = (ds.i - LV_MATH_MIN(ext->w, ext->h)) / 2;
|
||||
img->ext_draw_pad = LV_MATH_MAX(img->ext_draw_pad, d);
|
||||
|
@ -43,9 +43,11 @@ 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)*/
|
||||
uint16_t angle;
|
||||
uint16_t zoom; /*256 means no zoom, 512 double size, 128 hasl size*/
|
||||
uint8_t src_type : 2; /*See: lv_img_src_t*/
|
||||
uint8_t auto_size : 1; /*1: automatically set the object size to the image size*/
|
||||
uint8_t cf : 5; /*Color format from `lv_img_color_format_t`*/
|
||||
uint8_t antialias :1; /*Apply anti-aliasing in transformations (rotate, zoom)*/
|
||||
} lv_img_ext_t;
|
||||
|
||||
/*Styles*/
|
||||
@ -109,6 +111,25 @@ void lv_img_set_offset_y(lv_obj_t * img, lv_coord_t y);
|
||||
*/
|
||||
void lv_img_set_angle(lv_obj_t * img, int16_t angle);
|
||||
|
||||
/**
|
||||
* Set the zoom factor of the image.
|
||||
* @param img pointer to an image object
|
||||
* @param zoom the zoom factor.
|
||||
* - 256 or LV_ZOOM_IMG_NONE for no zoom
|
||||
* - <256: scale down
|
||||
* - >256 scale up
|
||||
* - 128 half size
|
||||
* - 512 double size
|
||||
*/
|
||||
void lv_img_set_zoom(lv_obj_t * img, uint16_t zoom);
|
||||
|
||||
/**
|
||||
* Enable/disable anti-aliasing for the transformations (rotate, zoom) or not
|
||||
* @param img pointer to an image object
|
||||
* @param antialias true: anti-aliased; false: not anti-aliased
|
||||
*/
|
||||
void lv_img_set_antialais(lv_obj_t * img, bool antialias);
|
||||
|
||||
/**
|
||||
* Set the style of an image
|
||||
* @param img pointer to an image object
|
||||
@ -167,6 +188,20 @@ lv_coord_t lv_img_get_offset_y(lv_obj_t * img);
|
||||
*/
|
||||
uint16_t lv_img_get_angle(lv_obj_t * img);
|
||||
|
||||
/**
|
||||
* Get the zoom factor of the image.
|
||||
* @param img pointer to an image object
|
||||
* @return zoom factor (256: no zoom)
|
||||
*/
|
||||
uint16_t lv_img_get_zoom(lv_obj_t * img);
|
||||
|
||||
/**
|
||||
* Get whether the transformations (rotate, zoom) are anti-aliased or not
|
||||
* @param img pointer to an image object
|
||||
* @return true: anti-aliased; false: not anti-aliased
|
||||
*/
|
||||
bool lv_img_get_antialais(lv_obj_t * img);
|
||||
|
||||
/**
|
||||
* Get the style of an image object
|
||||
* @param img pointer to an image object
|
||||
|
@ -303,7 +303,7 @@ static lv_design_res_t lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * cli
|
||||
if(lv_img_src_get_type(src) == LV_IMG_SRC_SYMBOL) {
|
||||
lv_draw_label(&imgbtn->coords, clip_area, style, opa_scale, src, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
|
||||
} else {
|
||||
lv_draw_img(&imgbtn->coords, clip_area, src, style, 0, opa_scale);
|
||||
lv_draw_img(&imgbtn->coords, clip_area, src, style, 0, LV_IMG_ZOOM_NONE, false, opa_scale);
|
||||
}
|
||||
#else
|
||||
const void * src = ext->img_src_left[state];
|
||||
|
@ -71,7 +71,7 @@ lv_obj_t * lv_objmask_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Init the new object mask object mask*/
|
||||
if(copy == NULL) {
|
||||
lv_objmask_set_style(new_objmask, LV_OBJMASK_STYLE_BG, &lv_style_plain);
|
||||
lv_objmask_set_style(new_objmask, LV_OBJMASK_STYLE_BG, &lv_style_transp);
|
||||
|
||||
}
|
||||
/*Copy an existing object mask*/
|
||||
|
@ -84,6 +84,7 @@ lv_obj_t * lv_preload_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
ext->arc_length = LV_PRELOAD_DEF_ARC_LENGTH;
|
||||
ext->anim_type = LV_PRELOAD_DEF_ANIM;
|
||||
ext->anim_dir = LV_PRELOAD_DIR_FORWARD;
|
||||
ext->time = LV_PRELOAD_DEF_SPIN_TIME;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_cb(new_preload, lv_preload_signal);
|
||||
@ -101,7 +102,6 @@ lv_obj_t * lv_preload_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
lv_obj_set_style(new_preload, &lv_style_pretty_color);
|
||||
}
|
||||
|
||||
ext->time = LV_PRELOAD_DEF_SPIN_TIME;
|
||||
|
||||
}
|
||||
/*Copy an existing pre loader*/
|
||||
@ -352,7 +352,8 @@ void lv_preload_spinner_anim(void * ptr, lv_anim_value_t val)
|
||||
lv_obj_t * preload = ptr;
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
|
||||
int16_t angle_start = val - ext->arc_length / 2 + 180;
|
||||
int16_t angle_start = val - ext->arc_length / 2 - 90;
|
||||
if(angle_start < 0) angle_start += 360;
|
||||
int16_t angle_end = angle_start + ext->arc_length;
|
||||
|
||||
angle_start = angle_start % 360;
|
||||
|
Loading…
x
Reference in New Issue
Block a user