1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-21 06:53:01 +08:00

draw_mask updates + lv_objmask use relative coordinates with masks

This commit is contained in:
Gabor Kiss-Vamosi 2019-11-14 07:16:24 +01:00
parent 90b7d3853f
commit cbe99407b0
13 changed files with 390 additions and 271 deletions

View File

@ -2439,17 +2439,18 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area
lv_draw_rect(&obj->coords, clip_area, style, lv_obj_get_opa_scale(obj)); lv_draw_rect(&obj->coords, clip_area, style, lv_obj_get_opa_scale(obj));
if(style->body.corner_mask) { if(style->body.corner_mask) {
lv_draw_mask_param_t * mp = lv_draw_buf_get(sizeof(lv_draw_mask_param_t)); lv_draw_mask_radius_param_t * mp = lv_draw_buf_get(sizeof(lv_draw_mask_radius_param_t));
lv_draw_mask_radius_init(mp, &obj->coords, style->body.radius, false); lv_draw_mask_radius_init(mp, &obj->coords, style->body.radius, false);
lv_draw_mask_add(mp, obj + 4); /*Add the mask and use `obj+8` as custom id. Don't use `obj` directly because it might be sued by the user*/
lv_draw_mask_add(mp, obj + 8);
} }
} }
else if(mode == LV_DESIGN_DRAW_POST) { else if(mode == LV_DESIGN_DRAW_POST) {
const lv_style_t * style = lv_obj_get_style(obj); const lv_style_t * style = lv_obj_get_style(obj);
if(style->body.corner_mask) { if(style->body.corner_mask) {
lv_draw_mask_param_t * mp = lv_draw_mask_remove_custom(obj + 4); lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8);
lv_draw_buf_release(mp); lv_draw_buf_release(param);
} }
} }

View File

@ -27,7 +27,7 @@ extern "C" {
* DEFINES * DEFINES
*********************/ *********************/
#ifndef LV_DRAW_BUF_MAX_NUM #ifndef LV_DRAW_BUF_MAX_NUM
#define LV_DRAW_BUF_MAX_NUM 8 #define LV_DRAW_BUF_MAX_NUM 12
#endif #endif
/********************** /**********************

View File

@ -55,7 +55,7 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
circle_style.body.border.width = style->line.width; circle_style.body.border.width = style->line.width;
circle_style.body.border.color = style->line.color; circle_style.body.border.color = style->line.color;
lv_draw_mask_param_t mask_angle_param; lv_draw_mask_angle_param_t mask_angle_param;
lv_draw_mask_angle_init(&mask_angle_param, center_x, center_y, start_angle, end_angle); lv_draw_mask_angle_init(&mask_angle_param, center_x, center_y, start_angle, end_angle);
int16_t mask_angle_id = lv_draw_mask_add(&mask_angle_param, NULL); int16_t mask_angle_id = lv_draw_mask_add(&mask_angle_param, NULL);

View File

@ -275,10 +275,10 @@ static void draw_line_skew(const lv_point_t * point1, const lv_point_t * point2,
bool is_common = lv_area_intersect(&draw_area, &draw_area, clip); bool is_common = lv_area_intersect(&draw_area, &draw_area, clip);
if(is_common == false) return; if(is_common == false) return;
lv_draw_mask_param_t mask_left_param; lv_draw_mask_line_param_t mask_left_param;
lv_draw_mask_param_t mask_right_param; lv_draw_mask_line_param_t mask_right_param;
lv_draw_mask_param_t mask_top_param; lv_draw_mask_line_param_t mask_top_param;
lv_draw_mask_param_t mask_bottom_param; lv_draw_mask_line_param_t mask_bottom_param;
if(flat) { if(flat) {
if(xdiff > 0) { if(xdiff > 0) {

View File

@ -21,19 +21,18 @@
**********************/ **********************/
typedef struct typedef struct
{ {
lv_draw_mask_param_t * param; void * param;
void * custom_id; void * custom_id;
}lv_mask_saved_t; }lv_mask_saved_t;
/********************** /**********************
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
static lv_draw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_param_t * param); static lv_draw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_line_param_t * param);
static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_param_t * param); static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_radius_param_t * param);
static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_param_t * param); static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_angle_param_t * param);
static lv_draw_mask_res_t lv_draw_mask_fade(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_param_t * param); static lv_draw_mask_res_t lv_draw_mask_fade(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_fade_param_t * param);
static lv_draw_mask_res_t lv_draw_mask_map(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_param_t * param); static lv_draw_mask_res_t lv_draw_mask_map(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_map_param_t * param);
static lv_draw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_line_param_t * p); static lv_draw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_line_param_t * p);
static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_line_param_t * p); static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_line_param_t * p);
@ -59,9 +58,9 @@ static lv_mask_saved_t mask_list[LV_MASK_MAX_NUM];
* @param custom_id a custom pointer to identify the mask. Used in `lv_draw_mask_remove_custom`. * @param custom_id a custom pointer to identify the mask. Used in `lv_draw_mask_remove_custom`.
* @return the an integer, the ID of the mask. Can be used in `lv_draw_mask_remove_id`. * @return the an integer, the ID of the mask. Can be used in `lv_draw_mask_remove_id`.
*/ */
int16_t lv_draw_mask_add(lv_draw_mask_param_t * param, void * custom_id) int16_t lv_draw_mask_add(void * param, void * custom_id)
{ {
/*Search a free entry*/ /*Look for a free entry*/
uint8_t i; uint8_t i;
for(i = 0; i < LV_MASK_MAX_NUM; i++) { for(i = 0; i < LV_MASK_MAX_NUM; i++) {
if(mask_list[i].param == NULL) break; if(mask_list[i].param == NULL) break;
@ -92,11 +91,14 @@ int16_t lv_draw_mask_add(lv_draw_mask_param_t * param, void * custom_id)
lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len) lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len)
{ {
bool changed = false; bool changed = false;
lv_draw_mask_common_dsc_t * dsc;
lv_draw_mask_res_t res = LV_DRAW_MASK_RES_FULL_COVER; lv_draw_mask_res_t res = LV_DRAW_MASK_RES_FULL_COVER;
uint8_t i; uint8_t i;
for(i = 0; i < LV_MASK_MAX_NUM; i++) { for(i = 0; i < LV_MASK_MAX_NUM; i++) {
if(mask_list[i].param) { if(mask_list[i].param) {
res = mask_list[i].param->line.cb(mask_buf, abs_x, abs_y, len, (void*)mask_list[i].param); dsc = mask_list[i].param;
res = dsc->cb(mask_buf, abs_x, abs_y, len, (void*)mask_list[i].param);
if(res == LV_DRAW_MASK_RES_FULL_TRANSP) return LV_DRAW_MASK_RES_FULL_TRANSP; if(res == LV_DRAW_MASK_RES_FULL_TRANSP) return LV_DRAW_MASK_RES_FULL_TRANSP;
else if(res == LV_DRAW_MASK_RES_CHANGED) changed = true; else if(res == LV_DRAW_MASK_RES_CHANGED) changed = true;
} }
@ -111,9 +113,9 @@ lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_
* @return the parameter of the removed mask. * @return the parameter of the removed mask.
* If more masks have `custom_id` ID then the last mask's parameter will be returned * If more masks have `custom_id` ID then the last mask's parameter will be returned
*/ */
lv_draw_mask_param_t * lv_draw_mask_remove_id(int16_t id) void * lv_draw_mask_remove_id(int16_t id)
{ {
lv_draw_mask_param_t * p = NULL; void * p = NULL;
if(id != LV_MASK_ID_INV) { if(id != LV_MASK_ID_INV) {
p = mask_list[id].param; p = mask_list[id].param;
@ -121,7 +123,7 @@ lv_draw_mask_param_t * lv_draw_mask_remove_id(int16_t id)
mask_list[id].custom_id = NULL; mask_list[id].custom_id = NULL;
} }
return NULL; return p;
} }
/** /**
@ -130,9 +132,9 @@ lv_draw_mask_param_t * lv_draw_mask_remove_id(int16_t id)
* @return return the parameter of the removed mask. * @return return the parameter of the removed mask.
* If more masks have `custom_id` ID then the last mask's parameter will be returned * If more masks have `custom_id` ID then the last mask's parameter will be returned
*/ */
lv_draw_mask_param_t * lv_draw_mask_remove_custom(void * custom_id) void * lv_draw_mask_remove_custom(void * custom_id)
{ {
lv_draw_mask_param_t * p = NULL; void * p = NULL;
uint8_t i; uint8_t i;
for(i = 0; i < LV_MASK_MAX_NUM; i++) { for(i = 0; i < LV_MASK_MAX_NUM; i++) {
if(mask_list[i].custom_id == custom_id) { if(mask_list[i].custom_id == custom_id) {
@ -169,10 +171,9 @@ uint8_t lv_draw_mask_get_cnt(void)
* With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept * With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept
* With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept * With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept
*/ */
void lv_draw_mask_line_points_init(lv_draw_mask_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x, lv_coord_t p2y, lv_draw_mask_line_side_t side) void lv_draw_mask_line_points_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x, lv_coord_t p2y, lv_draw_mask_line_side_t side)
{ {
lv_draw_mask_line_param_t * p = &param->line; memset(param, 0x00, sizeof(lv_draw_mask_line_param_t));
memset(p, 0x00, sizeof(lv_draw_mask_line_param_t));
if(p1y > p2y) { if(p1y > p2y) {
lv_coord_t t; lv_coord_t t;
@ -185,60 +186,66 @@ void lv_draw_mask_line_points_init(lv_draw_mask_param_t * param, lv_coord_t p1x,
p1y = t; p1y = t;
} }
p->origo.x = p1x; param->cfg.p1.x = p1x;
p->origo.y = p1y; param->cfg.p1.y = p1y;
p->side = side; param->cfg.p2.x = p1x;
p->flat = (LV_MATH_ABS(p2x-p1x) > LV_MATH_ABS(p2y-p1y)) ? 1 : 0; param->cfg.p2.y = p1y;
p->yx_steep = 0; param->cfg.side = side;
p->xy_steep = 0;
p->cb = lv_draw_mask_line; param->origo.x = p1x;
param->origo.y = p1y;
param->flat = (LV_MATH_ABS(p2x-p1x) > LV_MATH_ABS(p2y-p1y)) ? 1 : 0;
param->yx_steep = 0;
param->xy_steep = 0;
param->dsc.cb = (lv_draw_mask_cb_t)lv_draw_mask_line;
param->dsc.type = LV_DRAW_MASK_TYPE_LINE;
lv_coord_t dx = p2x-p1x; lv_coord_t dx = p2x-p1x;
lv_coord_t dy = p2y-p1y; lv_coord_t dy = p2y-p1y;
if(p->flat) { if(param->flat) {
/*Normalize the steep. Delta x should be relative to delta x = 1024*/ /*Normalize the steep. Delta x should be relative to delta x = 1024*/
int32_t m; int32_t m;
if(dx) { if(dx) {
m = (1 << 20) / dx; /*m is multiplier to normalize y (upscaled by 1024)*/ m = (1 << 20) / dx; /*m is multiplier to normalize y (upscaled by 1024)*/
p->yx_steep = (m * dy) >> 10; param->yx_steep = (m * dy) >> 10;
} }
if(dy) { if(dy) {
m = (1 << 20) / dy; /*m is multiplier to normalize x (upscaled by 1024)*/ m = (1 << 20) / dy; /*m is multiplier to normalize x (upscaled by 1024)*/
p->xy_steep = (m * dx) >> 10; param->xy_steep = (m * dx) >> 10;
} }
p->steep = p->yx_steep; param->steep = param->yx_steep;
} else { } else {
/*Normalize the steep. Delta y should be relative to delta x = 1024*/ /*Normalize the steep. Delta y should be relative to delta x = 1024*/
int32_t m; int32_t m;
if(dy) { if(dy) {
m = (1 << 20) / dy; /*m is multiplier to normalize x (upscaled by 1024)*/ m = (1 << 20) / dy; /*m is multiplier to normalize x (upscaled by 1024)*/
p->xy_steep = (m * dx) >> 10; param->xy_steep = (m * dx) >> 10;
} }
if(dx) { if(dx) {
m = (1 << 20) / dx; /*m is multiplier to normalize x (upscaled by 1024)*/ m = (1 << 20) / dx; /*m is multiplier to normalize x (upscaled by 1024)*/
p->yx_steep = (m * dy) >> 10; param->yx_steep = (m * dy) >> 10;
} }
p->steep = p->xy_steep; param->steep = param->xy_steep;
} }
if(p->side == LV_DRAW_MASK_LINE_SIDE_LEFT) p->inv = 0; if(param->cfg.side == LV_DRAW_MASK_LINE_SIDE_LEFT) param->inv = 0;
else if(p->side == LV_DRAW_MASK_LINE_SIDE_RIGHT) p->inv = 1; else if(param->cfg.side == LV_DRAW_MASK_LINE_SIDE_RIGHT) param->inv = 1;
else if(p->side == LV_DRAW_MASK_LINE_SIDE_TOP) { else if(param->cfg.side == LV_DRAW_MASK_LINE_SIDE_TOP) {
if(p->steep > 0) p->inv = 1; if(param->steep > 0) param->inv = 1;
else p->inv = 0; else param->inv = 0;
} }
else if(p->side == LV_DRAW_MASK_LINE_SIDE_BOTTOM) { else if(param->cfg.side == LV_DRAW_MASK_LINE_SIDE_BOTTOM) {
if(p->steep > 0) p->inv = 0; if(param->steep > 0) param->inv = 0;
else p->inv = 1; else param->inv = 1;
} }
p->spx = p->steep >> 2; param->spx = param->steep >> 2;
if(p->steep < 0) p->spx = -p->spx; if(param->steep < 0) param->spx = -param->spx;
} }
/** /**
@ -251,7 +258,7 @@ void lv_draw_mask_line_points_init(lv_draw_mask_param_t * param, lv_coord_t p1x,
* With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept * With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept
* With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept * With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept
*/ */
void lv_draw_mask_line_angle_init(lv_draw_mask_param_t * param, lv_coord_t p1x, lv_coord_t py, int16_t angle, lv_draw_mask_line_side_t side) void lv_draw_mask_line_angle_init(lv_draw_mask_line_param_t* param, lv_coord_t p1x, lv_coord_t py, int16_t angle, lv_draw_mask_line_side_t side)
{ {
/* Find an optimal degree. /* Find an optimal degree.
* lv_mask_line_points_init will swap the points to keep the smaller y in p1 * lv_mask_line_points_init will swap the points to keep the smaller y in p1
@ -278,10 +285,8 @@ void lv_draw_mask_line_angle_init(lv_draw_mask_param_t * param, lv_coord_t p1x,
* @param start_angle start angle in degrees. 0 deg on the right, 90 deg, on the bottom * @param start_angle start angle in degrees. 0 deg on the right, 90 deg, on the bottom
* @param end_angle end angle * @param end_angle end angle
*/ */
void lv_draw_mask_angle_init(lv_draw_mask_param_t * param, lv_coord_t vertex_x, lv_coord_t vertex_y, lv_coord_t start_angle, lv_coord_t end_angle) void lv_draw_mask_angle_init(lv_draw_mask_angle_param_t * param, lv_coord_t vertex_x, lv_coord_t vertex_y, lv_coord_t start_angle, lv_coord_t end_angle)
{ {
lv_draw_mask_angle_param_t * p = &param->angle;
lv_draw_mask_line_side_t start_side; lv_draw_mask_line_side_t start_side;
lv_draw_mask_line_side_t end_side; lv_draw_mask_line_side_t end_side;
@ -297,16 +302,17 @@ void lv_draw_mask_angle_init(lv_draw_mask_param_t * param, lv_coord_t vertex_x,
end_angle = 359; end_angle = 359;
if(end_angle < start_angle) { if(end_angle < start_angle) {
p->delta_deg = 360 - start_angle + end_angle; param->delta_deg = 360 - start_angle + end_angle;
} else { } else {
p->delta_deg = LV_MATH_ABS(end_angle - start_angle); param->delta_deg = LV_MATH_ABS(end_angle - start_angle);
} }
p->start_angle = start_angle; param->cfg.start_angle = start_angle;
p->end_angle = end_angle; param->cfg.end_angle = end_angle;
p->vertex.x = vertex_x; param->cfg.vertex_p.x = vertex_x;
p->vertex.y = vertex_y; param->cfg.vertex_p.y = vertex_y;
p->cb = lv_draw_mask_angle; param->dsc.cb = (lv_draw_mask_cb_t)lv_draw_mask_angle;
param->dsc.type = LV_DRAW_MASK_TYPE_ANGLE;
if(start_angle >= 0 && start_angle < 180) { if(start_angle >= 0 && start_angle < 180) {
start_side = LV_DRAW_MASK_LINE_SIDE_LEFT; start_side = LV_DRAW_MASK_LINE_SIDE_LEFT;
@ -326,8 +332,8 @@ void lv_draw_mask_angle_init(lv_draw_mask_param_t * param, lv_coord_t vertex_x,
LV_DEBUG_ASSERT(false, "Unexpected end_angle", end_angle); LV_DEBUG_ASSERT(false, "Unexpected end_angle", end_angle);
} }
lv_draw_mask_line_angle_init((lv_draw_mask_param_t*)&p->start_line, vertex_x, vertex_y, start_angle, start_side); lv_draw_mask_line_angle_init(&param->start_line, vertex_x, vertex_y, start_angle, start_side);
lv_draw_mask_line_angle_init((lv_draw_mask_param_t*)&p->end_line, vertex_x, vertex_y, end_angle, end_side); lv_draw_mask_line_angle_init(&param->end_line, vertex_x, vertex_y, end_angle, end_side);
} }
@ -338,17 +344,17 @@ void lv_draw_mask_angle_init(lv_draw_mask_param_t * param, lv_coord_t vertex_x,
* @param radius radius of the rectangle * @param radius radius of the rectangle
* @param inv: true: keep the pixels inside teh rectangle; keep teh pixels outside of the rectangle * @param inv: true: keep the pixels inside teh rectangle; keep teh pixels outside of the rectangle
*/ */
void lv_draw_mask_radius_init(lv_draw_mask_param_t * param, const lv_area_t * rect, lv_coord_t radius, bool inv) void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area_t * rect, lv_coord_t radius, bool inv)
{ {
lv_draw_mask_radius_param_t * p = &param->radius;
lv_coord_t short_side = LV_MATH_MIN(lv_area_get_width(rect), lv_area_get_height(rect)); lv_coord_t short_side = LV_MATH_MIN(lv_area_get_width(rect), lv_area_get_height(rect));
if(radius > short_side >> 1) radius = short_side >> 1; if(radius > short_side >> 1) radius = short_side >> 1;
lv_area_copy(&p->rect, rect); lv_area_copy(&param->cfg.rect, rect);
p->radius = radius; param->cfg.radius = radius;
p->inv = inv ? 1 : 0; param->cfg.outer = inv ? 1 : 0;
p->cb = lv_draw_mask_radius; param->dsc.cb = (lv_draw_mask_cb_t)lv_draw_mask_radius;
param->dsc.type = LV_DRAW_MASK_TYPE_RADIUS;
} }
@ -361,16 +367,15 @@ void lv_draw_mask_radius_init(lv_draw_mask_param_t * param, const lv_area_t * re
* @param opa_bottom opacity at the bottom * @param opa_bottom opacity at the bottom
* @param y_bottom at which coordinate reach `opa_bottom`. * @param y_bottom at which coordinate reach `opa_bottom`.
*/ */
void lv_draw_mask_fade_init(lv_draw_mask_param_t * param, lv_area_t * coords, lv_opa_t opa_top, lv_coord_t y_top, lv_opa_t opa_bottom, lv_coord_t y_bottom) void lv_draw_mask_fade_init(lv_draw_mask_fade_param_t * param, lv_area_t * coords, lv_opa_t opa_top, lv_coord_t y_top, lv_opa_t opa_bottom, lv_coord_t y_bottom)
{ {
lv_draw_mask_fade_param_t * p = &param->fade; lv_area_copy(&param->cfg.coords, coords);
param->cfg.opa_top= opa_top;
lv_area_copy(&p->coords, coords); param->cfg.opa_bottom = opa_bottom;
p->opa_top= opa_top; param->cfg.y_top= y_top;
p->opa_bottom = opa_bottom; param->cfg.y_bottom = y_bottom;
p->y_top= y_top; param->dsc.cb = (lv_draw_mask_cb_t)lv_draw_mask_fade;
p->y_bottom = y_bottom; param->dsc.type = LV_DRAW_MASK_TYPE_FADE;
p->cb = lv_draw_mask_fade;
} }
@ -380,13 +385,12 @@ void lv_draw_mask_fade_init(lv_draw_mask_param_t * param, lv_area_t * coords, lv
* @param coords coordinates of the map (absolute coordinates) * @param coords coordinates of the map (absolute coordinates)
* @param map array of bytes with the mask values * @param map array of bytes with the mask values
*/ */
void lv_draw_mask_map_init(lv_draw_mask_param_t * param, lv_area_t * coords, const lv_opa_t * map) void lv_draw_mask_map_init(lv_draw_mask_map_param_t * param, lv_area_t * coords, const lv_opa_t * map)
{ {
lv_draw_mask_map_param_t * p = &param->map; lv_area_copy(&param->cfg.coords, coords);
param->cfg.map = map;
lv_area_copy(&p->coords, coords); param->dsc.cb = (lv_draw_mask_cb_t)lv_draw_mask_map;
p->map = map; param->dsc.type = LV_DRAW_MASK_TYPE_MAP;
p->cb = lv_draw_mask_map;
} }
@ -394,10 +398,8 @@ void lv_draw_mask_map_init(lv_draw_mask_param_t * param, lv_area_t * coords, con
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
static lv_draw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_param_t * param) static lv_draw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_line_param_t * p)
{ {
lv_draw_mask_line_param_t * p = &param->line;
/*Make to points relative to the vertex*/ /*Make to points relative to the vertex*/
abs_y -= p->origo.y; abs_y -= p->origo.y;
abs_x -= p->origo.x; abs_x -= p->origo.x;
@ -407,9 +409,9 @@ static lv_draw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_
/*Horizontal*/ /*Horizontal*/
if(p->flat) { if(p->flat) {
/*Non sense: Can't be on the right/left of a horizontal line*/ /*Non sense: Can't be on the right/left of a horizontal line*/
if(p->side == LV_DRAW_MASK_LINE_SIDE_LEFT || p->side == LV_DRAW_MASK_LINE_SIDE_RIGHT) return LV_DRAW_MASK_RES_FULL_COVER; if(p->cfg.side == LV_DRAW_MASK_LINE_SIDE_LEFT || p->cfg.side == LV_DRAW_MASK_LINE_SIDE_RIGHT) return LV_DRAW_MASK_RES_FULL_COVER;
else if(p->side == LV_DRAW_MASK_LINE_SIDE_TOP && abs_y+1 < 0) return LV_DRAW_MASK_RES_FULL_COVER; else if(p->cfg.side == LV_DRAW_MASK_LINE_SIDE_TOP && abs_y+1 < 0) return LV_DRAW_MASK_RES_FULL_COVER;
else if(p->side == LV_DRAW_MASK_LINE_SIDE_BOTTOM && abs_y > 0) return LV_DRAW_MASK_RES_FULL_COVER; else if(p->cfg.side == LV_DRAW_MASK_LINE_SIDE_BOTTOM && abs_y > 0) return LV_DRAW_MASK_RES_FULL_COVER;
else { else {
return LV_DRAW_MASK_RES_FULL_TRANSP; return LV_DRAW_MASK_RES_FULL_TRANSP;
} }
@ -417,9 +419,9 @@ static lv_draw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_
/*Vertical*/ /*Vertical*/
else { else {
/*Non sense: Can't be on the top/bottom of a vertical line*/ /*Non sense: Can't be on the top/bottom of a vertical line*/
if(p->side == LV_DRAW_MASK_LINE_SIDE_TOP || p->side == LV_DRAW_MASK_LINE_SIDE_BOTTOM) return LV_DRAW_MASK_RES_FULL_COVER; if(p->cfg.side == LV_DRAW_MASK_LINE_SIDE_TOP || p->cfg.side == LV_DRAW_MASK_LINE_SIDE_BOTTOM) return LV_DRAW_MASK_RES_FULL_COVER;
else if(p->side == LV_DRAW_MASK_LINE_SIDE_RIGHT && abs_x > 0) return LV_DRAW_MASK_RES_FULL_COVER; else if(p->cfg.side == LV_DRAW_MASK_LINE_SIDE_RIGHT && abs_x > 0) return LV_DRAW_MASK_RES_FULL_COVER;
else if(p->side == LV_DRAW_MASK_LINE_SIDE_LEFT) { else if(p->cfg.side == LV_DRAW_MASK_LINE_SIDE_LEFT) {
if(abs_x + len < 0) return LV_DRAW_MASK_RES_FULL_COVER; if(abs_x + len < 0) return LV_DRAW_MASK_RES_FULL_COVER;
else { else {
int32_t k = - abs_x; int32_t k = - abs_x;
@ -693,17 +695,17 @@ static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x,
} }
static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_param_t * param) static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_angle_param_t * p)
{ {
lv_draw_mask_angle_param_t * p = &param->angle; lv_coord_t rel_y = abs_y - p->cfg.vertex_p.y;
lv_coord_t rel_x = abs_x - p->cfg.vertex_p.x;
lv_coord_t rel_y = abs_y - p->vertex.y;
lv_coord_t rel_x = abs_x - p->vertex.x;
if(p->start_angle < 180 && p->end_angle < 180 && p->start_angle != 0 && p->end_angle != 0 && p->start_angle > p->end_angle) { if(p->cfg.start_angle < 180 && p->cfg.end_angle < 180 &&
p->cfg.start_angle != 0 && p->cfg.end_angle != 0 &&
p->cfg.start_angle > p->cfg.end_angle) {
if(abs_y < p->vertex.y) { if(abs_y < p->cfg.vertex_p.y) {
return LV_DRAW_MASK_RES_FULL_COVER; return LV_DRAW_MASK_RES_FULL_COVER;
} }
@ -713,13 +715,13 @@ static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs
/*Do not let the line end cross the vertex else it will affect the opposite part*/ /*Do not let the line end cross the vertex else it will affect the opposite part*/
if(p->start_angle > 270 && p->start_angle <= 359 && start_angle_last < 0) start_angle_last = 0; if(p->cfg.start_angle > 270 && p->cfg.start_angle <= 359 && start_angle_last < 0) start_angle_last = 0;
else if(p->start_angle > 0 && p->start_angle <= 90 && start_angle_last < 0) start_angle_last = 0; else if(p->cfg.start_angle > 0 && p->cfg.start_angle <= 90 && start_angle_last < 0) start_angle_last = 0;
else if(p->start_angle > 90 && p->start_angle < 270 && start_angle_last > 0) start_angle_last = 0; else if(p->cfg.start_angle > 90 && p->cfg.start_angle < 270 && start_angle_last > 0) start_angle_last = 0;
if(p->end_angle > 270 && p->end_angle <= 359 && start_angle_last < 0) start_angle_last = 0; if(p->cfg.end_angle > 270 && p->cfg.end_angle <= 359 && start_angle_last < 0) start_angle_last = 0;
else if(p->end_angle > 0 && p->end_angle <= 90 && start_angle_last < 0) start_angle_last = 0; else if(p->cfg.end_angle > 0 && p->cfg.end_angle <= 90 && start_angle_last < 0) start_angle_last = 0;
else if(p->end_angle > 90 && p->end_angle < 270 && start_angle_last > 0) start_angle_last = 0; else if(p->cfg.end_angle > 90 && p->cfg.end_angle < 270 && start_angle_last > 0) start_angle_last = 0;
int32_t dist = (end_angle_first - start_angle_last) >> 1; int32_t dist = (end_angle_first - start_angle_last) >> 1;
@ -730,7 +732,7 @@ static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs
int32_t tmp = start_angle_last + dist - rel_x; int32_t tmp = start_angle_last + dist - rel_x;
if(tmp > len) tmp = len; if(tmp > len) tmp = len;
if(tmp > 0) { if(tmp > 0) {
res1 = lv_draw_mask_line(&mask_buf[0], abs_x, abs_y, tmp, (lv_draw_mask_param_t*)&p->start_line); res1 = lv_draw_mask_line(&mask_buf[0], abs_x, abs_y, tmp, &p->start_line);
if(res1 == LV_DRAW_MASK_RES_FULL_TRANSP) { if(res1 == LV_DRAW_MASK_RES_FULL_TRANSP) {
memset(&mask_buf[0], 0x00, tmp); memset(&mask_buf[0], 0x00, tmp);
} }
@ -738,16 +740,16 @@ static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs
if(tmp > len) tmp = len; if(tmp > len) tmp = len;
if(tmp < 0) tmp = 0; if(tmp < 0) tmp = 0;
res2 = lv_draw_mask_line(&mask_buf[tmp], abs_x+tmp, abs_y, len-tmp, (lv_draw_mask_param_t*)&p->end_line); res2 = lv_draw_mask_line(&mask_buf[tmp], abs_x+tmp, abs_y, len-tmp, &p->end_line);
if(res2 == LV_DRAW_MASK_RES_FULL_TRANSP) { if(res2 == LV_DRAW_MASK_RES_FULL_TRANSP) {
memset(&mask_buf[tmp], 0x00, len-tmp); memset(&mask_buf[tmp], 0x00, len-tmp);
} }
if(res1 == res2) return res1; if(res1 == res2) return res1;
else return LV_DRAW_MASK_RES_CHANGED; else return LV_DRAW_MASK_RES_CHANGED;
} }
else if(p->start_angle > 180 && p->end_angle > 180 && p->start_angle > p->end_angle) { else if(p->cfg.start_angle > 180 && p->cfg.end_angle > 180 && p->cfg.start_angle > p->cfg.end_angle) {
if(abs_y > p->vertex.y) { if(abs_y > p->cfg.vertex_p.y) {
return LV_DRAW_MASK_RES_FULL_COVER; return LV_DRAW_MASK_RES_FULL_COVER;
} }
@ -756,13 +758,13 @@ static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs
lv_coord_t start_angle_last= ((rel_y+1) * p->start_line.xy_steep) >> 10; lv_coord_t start_angle_last= ((rel_y+1) * p->start_line.xy_steep) >> 10;
/*Do not let the line end cross the vertex else it will affect the opposite part*/ /*Do not let the line end cross the vertex else it will affect the opposite part*/
if(p->start_angle > 270 && p->start_angle <= 359 && start_angle_last < 0) start_angle_last = 0; if(p->cfg.start_angle > 270 && p->cfg.start_angle <= 359 && start_angle_last < 0) start_angle_last = 0;
else if(p->start_angle > 0 && p->start_angle <= 90 && start_angle_last < 0) start_angle_last = 0; else if(p->cfg.start_angle > 0 && p->cfg.start_angle <= 90 && start_angle_last < 0) start_angle_last = 0;
else if(p->start_angle > 90 && p->start_angle < 270 && start_angle_last > 0) start_angle_last = 0; else if(p->cfg.start_angle > 90 && p->cfg.start_angle < 270 && start_angle_last > 0) start_angle_last = 0;
if(p->end_angle > 270 && p->end_angle <= 359 && start_angle_last < 0) start_angle_last = 0; if(p->cfg.end_angle > 270 && p->cfg.end_angle <= 359 && start_angle_last < 0) start_angle_last = 0;
else if(p->end_angle > 0 && p->end_angle <= 90 && start_angle_last < 0) start_angle_last = 0; else if(p->cfg.end_angle > 0 && p->cfg.end_angle <= 90 && start_angle_last < 0) start_angle_last = 0;
else if(p->end_angle > 90 && p->end_angle < 270 && start_angle_last > 0) start_angle_last = 0; else if(p->cfg.end_angle > 90 && p->cfg.end_angle < 270 && start_angle_last > 0) start_angle_last = 0;
int32_t dist = (end_angle_first - start_angle_last) >> 1; int32_t dist = (end_angle_first - start_angle_last) >> 1;
@ -772,7 +774,7 @@ static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs
int32_t tmp = start_angle_last + dist - rel_x; int32_t tmp = start_angle_last + dist - rel_x;
if(tmp > len) tmp = len; if(tmp > len) tmp = len;
if(tmp > 0) { if(tmp > 0) {
res1 = lv_draw_mask_line(&mask_buf[0], abs_x, abs_y, tmp, (lv_draw_mask_param_t*)&p->end_line); res1 = lv_draw_mask_line(&mask_buf[0], abs_x, abs_y, tmp, (lv_draw_mask_line_param_t*)&p->end_line);
if(res1 == LV_DRAW_MASK_RES_FULL_TRANSP) { if(res1 == LV_DRAW_MASK_RES_FULL_TRANSP) {
memset(&mask_buf[0], 0x00, tmp); memset(&mask_buf[0], 0x00, tmp);
} }
@ -780,7 +782,7 @@ static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs
if(tmp > len) tmp = len; if(tmp > len) tmp = len;
if(tmp < 0) tmp = 0; if(tmp < 0) tmp = 0;
res2 = lv_draw_mask_line(&mask_buf[tmp], abs_x+tmp, abs_y, len-tmp, (lv_draw_mask_param_t*)&p->start_line); res2 = lv_draw_mask_line(&mask_buf[tmp], abs_x+tmp, abs_y, len-tmp, (lv_draw_mask_line_param_t*)&p->start_line);
if(res2 == LV_DRAW_MASK_RES_FULL_TRANSP) { if(res2 == LV_DRAW_MASK_RES_FULL_TRANSP) {
memset(&mask_buf[tmp], 0x00, len-tmp); memset(&mask_buf[tmp], 0x00, len-tmp);
} }
@ -792,36 +794,36 @@ static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs
lv_draw_mask_res_t res1 = LV_DRAW_MASK_RES_FULL_COVER; lv_draw_mask_res_t res1 = LV_DRAW_MASK_RES_FULL_COVER;
lv_draw_mask_res_t res2 = LV_DRAW_MASK_RES_FULL_COVER; lv_draw_mask_res_t res2 = LV_DRAW_MASK_RES_FULL_COVER;
if(p->start_angle == 180) { if(p->cfg.start_angle == 180) {
if(abs_y < p->vertex.y) res1 = LV_DRAW_MASK_RES_FULL_COVER; if(abs_y < p->cfg.vertex_p.y) res1 = LV_DRAW_MASK_RES_FULL_COVER;
else res1 = LV_DRAW_MASK_RES_UNKNOWN; else res1 = LV_DRAW_MASK_RES_UNKNOWN;
} }
else if(p->start_angle == 0) { else if(p->cfg.start_angle == 0) {
if(abs_y < p->vertex.y) res1 = LV_DRAW_MASK_RES_UNKNOWN; if(abs_y < p->cfg.vertex_p.y) res1 = LV_DRAW_MASK_RES_UNKNOWN;
else res1 = LV_DRAW_MASK_RES_FULL_COVER; else res1 = LV_DRAW_MASK_RES_FULL_COVER;
} }
else if((p->start_angle < 180 && abs_y < p->vertex.y) || else if((p->cfg.start_angle < 180 && abs_y < p->cfg.vertex_p.y) ||
(p->start_angle > 180 && abs_y >= p->vertex.y)) { (p->cfg.start_angle > 180 && abs_y >= p->cfg.vertex_p.y)) {
res1 = LV_DRAW_MASK_RES_UNKNOWN; res1 = LV_DRAW_MASK_RES_UNKNOWN;
} }
else { else {
res1 = lv_draw_mask_line(mask_buf, abs_x, abs_y, len, (lv_draw_mask_param_t*)&p->start_line); res1 = lv_draw_mask_line(mask_buf, abs_x, abs_y, len, &p->start_line);
} }
if(p->end_angle == 180) { if(p->cfg.end_angle == 180) {
if(abs_y < p->vertex.y) res2 = LV_DRAW_MASK_RES_UNKNOWN; if(abs_y < p->cfg.vertex_p.y) res2 = LV_DRAW_MASK_RES_UNKNOWN;
else res2 = LV_DRAW_MASK_RES_FULL_COVER; else res2 = LV_DRAW_MASK_RES_FULL_COVER;
} }
else if(p->end_angle == 0) { else if(p->cfg.end_angle == 0) {
if(abs_y < p->vertex.y) res2 = LV_DRAW_MASK_RES_FULL_COVER; if(abs_y < p->cfg.vertex_p.y) res2 = LV_DRAW_MASK_RES_FULL_COVER;
else res2 = LV_DRAW_MASK_RES_UNKNOWN; else res2 = LV_DRAW_MASK_RES_UNKNOWN;
} }
else if((p->end_angle < 180 && abs_y < p->vertex.y) || else if((p->cfg.end_angle < 180 && abs_y < p->cfg.vertex_p.y) ||
(p->end_angle > 180 && abs_y >= p->vertex.y)) { (p->cfg.end_angle > 180 && abs_y >= p->cfg.vertex_p.y)) {
res2 = LV_DRAW_MASK_RES_UNKNOWN; res2 = LV_DRAW_MASK_RES_UNKNOWN;
} }
else { else {
res2 = lv_draw_mask_line(mask_buf, abs_x, abs_y, len, (lv_draw_mask_param_t*)&p->end_line); res2 = lv_draw_mask_line(mask_buf, abs_x, abs_y, len, &p->end_line);
} }
if(res1 == LV_DRAW_MASK_RES_FULL_TRANSP || res2 == LV_DRAW_MASK_RES_FULL_TRANSP) return LV_DRAW_MASK_RES_FULL_TRANSP; if(res1 == LV_DRAW_MASK_RES_FULL_TRANSP || res2 == LV_DRAW_MASK_RES_FULL_TRANSP) return LV_DRAW_MASK_RES_FULL_TRANSP;
@ -831,31 +833,29 @@ static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs
} }
} }
static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_param_t * param) static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_radius_param_t * p)
{ {
lv_draw_mask_radius_param_t * p = &param->radius; if(p->cfg.outer == 0) {
if(abs_y < p->cfg.rect.y1 || abs_y > p->cfg.rect.y2) {
if(p->inv == 0) {
if(abs_y < p->rect.y1 || abs_y > p->rect.y2) {
return LV_DRAW_MASK_RES_FULL_TRANSP; return LV_DRAW_MASK_RES_FULL_TRANSP;
} }
} else { } else {
if(abs_y < p->rect.y1 || abs_y > p->rect.y2) { if(abs_y < p->cfg.rect.y1 || abs_y > p->cfg.rect.y2) {
return LV_DRAW_MASK_RES_FULL_COVER; return LV_DRAW_MASK_RES_FULL_COVER;
} }
} }
if((abs_x >= p->rect.x1 + p->radius && abs_x + len <= p->rect.x2 - p->radius) || if((abs_x >= p->cfg.rect.x1 + p->cfg.radius && abs_x + len <= p->cfg.rect.x2 - p->cfg.radius) ||
(abs_y >= p->rect.y1 + p->radius && abs_y <= p->rect.y2 - p->radius)) { (abs_y >= p->cfg.rect.y1 + p->cfg.radius && abs_y <= p->cfg.rect.y2 - p->cfg.radius)) {
if(p->inv == 0) { if(p->cfg.outer == 0) {
/*Remove the edges*/ /*Remove the edges*/
int32_t last = p->rect.x1 - abs_x; int32_t last = p->cfg.rect.x1 - abs_x;
if(last > len) return LV_DRAW_MASK_RES_FULL_TRANSP; if(last > len) return LV_DRAW_MASK_RES_FULL_TRANSP;
if(last >= 0) { if(last >= 0) {
memset(&mask_buf[0], 0x00, last); memset(&mask_buf[0], 0x00, last);
} }
int32_t first = p->rect.x2 - abs_x + 1; int32_t first = p->cfg.rect.x2 - abs_x + 1;
if(first <= 0) return LV_DRAW_MASK_RES_FULL_TRANSP; if(first <= 0) return LV_DRAW_MASK_RES_FULL_TRANSP;
else if(first < len) { else if(first < len) {
memset(&mask_buf[first], 0x00, len-first); memset(&mask_buf[first], 0x00, len-first);
@ -864,10 +864,10 @@ static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t ab
else return LV_DRAW_MASK_RES_CHANGED; else return LV_DRAW_MASK_RES_CHANGED;
} }
else { else {
int32_t first = p->rect.x1 - abs_x; int32_t first = p->cfg.rect.x1 - abs_x;
if(first < 0) first = 0; if(first < 0) first = 0;
if(first <= len) { if(first <= len) {
int32_t last = p->rect.x2 - abs_x - first + 1; int32_t last = p->cfg.rect.x2 - abs_x - first + 1;
if(first + last > len) last = len - first; if(first + last > len) last = len - first;
if(last >= 0) { if(last >= 0) {
memset(&mask_buf[first], 0x00, last); memset(&mask_buf[first], 0x00, last);
@ -877,20 +877,20 @@ static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t ab
return LV_DRAW_MASK_RES_CHANGED; return LV_DRAW_MASK_RES_CHANGED;
} }
int32_t k = p->rect.x1 -abs_x; /*First relevant coordinate on the of the mask*/ int32_t k = p->cfg.rect.x1 -abs_x; /*First relevant coordinate on the of the mask*/
lv_coord_t w = lv_area_get_width(&p->rect); lv_coord_t w = lv_area_get_width(&p->cfg.rect);
lv_coord_t h = lv_area_get_height(&p->rect); lv_coord_t h = lv_area_get_height(&p->cfg.rect);
abs_x -= p->rect.x1; abs_x -= p->cfg.rect.x1;
abs_y -= p->rect.y1; abs_y -= p->cfg.rect.y1;
uint32_t r2 = p->radius * p->radius; uint32_t r2 = p->cfg.radius * p->cfg.radius;
/*Handle corner areas*/ /*Handle corner areas*/
if(abs_y < p->radius || abs_y > h - p->radius - 1) { if(abs_y < p->cfg.radius || abs_y > h - p->cfg.radius - 1) {
/* y = 0 should mean the top of the circle */ /* y = 0 should mean the top of the circle */
lv_coord_t y; lv_coord_t y;
if(abs_y < p->radius) y = p->radius - abs_y; if(abs_y < p->cfg.radius) y = p->cfg.radius - abs_y;
else y = p->radius - (h - abs_y) + 1; else y = p->cfg.radius - (h - abs_y) + 1;
/* Get the x intersection points for `abs_y` and `abs_y+1` /* Get the x intersection points for `abs_y` and `abs_y+1`
* Use the circle's equation x = sqrt(r^2 - y^2) */ * Use the circle's equation x = sqrt(r^2 - y^2) */
@ -910,8 +910,8 @@ static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t ab
/*If the two x intersections are on the same x then just get average of the fractionals*/ /*If the two x intersections are on the same x then just get average of the fractionals*/
if(x0.i == x1.i) { if(x0.i == x1.i) {
lv_opa_t m = (x0.f + x1.f) >> 1; lv_opa_t m = (x0.f + x1.f) >> 1;
if(p->inv) m = 255 - m; if(p->cfg.outer) m = 255 - m;
int32_t ofs = p->radius - x0.i - 1; int32_t ofs = p->cfg.radius - x0.i - 1;
/*Left corner*/ /*Left corner*/
int32_t kl = k + ofs; int32_t kl = k + ofs;
@ -927,7 +927,7 @@ static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t ab
} }
/*Clear the unused parts*/ /*Clear the unused parts*/
if(p->inv == 0) { if(p->cfg.outer == 0) {
kr++; kr++;
if(kl > len) { if(kl > len) {
return LV_DRAW_MASK_RES_FULL_TRANSP; return LV_DRAW_MASK_RES_FULL_TRANSP;
@ -955,11 +955,11 @@ static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t ab
} }
/*Multiple pixels are affected. Get y intersection of the pixels*/ /*Multiple pixels are affected. Get y intersection of the pixels*/
else { else {
int32_t ofs = p->radius - (x0.i + 1); int32_t ofs = p->cfg.radius - (x0.i + 1);
int32_t kl = k + ofs; int32_t kl = k + ofs;
int32_t kr = k + (w - ofs -1); int32_t kr = k + (w - ofs -1);
if(p->inv) { if(p->cfg.outer) {
int32_t first = kl + 1; int32_t first = kl + 1;
if(first < 0) first = 0; if(first < 0) first = 0;
@ -987,7 +987,7 @@ static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t ab
lv_sqrt(r2 - (i * i), &y_next); lv_sqrt(r2 - (i * i), &y_next);
m = 255 - (((255-x0.f) * (255 - y_next.f)) >> 9); m = 255 - (((255-x0.f) * (255 - y_next.f)) >> 9);
if(p->inv) m = 255 - m; if(p->cfg.outer) m = 255 - m;
if(kl >= 0 && kl < len) mask_buf[kl] = mask_mix(mask_buf[kl], m); if(kl >= 0 && kl < len) mask_buf[kl] = mask_mix(mask_buf[kl], m);
if(kr >= 0 && kr < len) mask_buf[kr] = mask_mix(mask_buf[kr], m); if(kr >= 0 && kr < len) mask_buf[kr] = mask_mix(mask_buf[kr], m);
kl--; kl--;
@ -1001,7 +1001,7 @@ static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t ab
lv_sqrt(r2 - (i * i), &y_next); lv_sqrt(r2 - (i * i), &y_next);
m = (y_prev.f + y_next.f) >> 1; m = (y_prev.f + y_next.f) >> 1;
if(p->inv) m = 255 - m; if(p->cfg.outer) m = 255 - m;
if(kl >= 0 && kl < len) mask_buf[kl] = mask_mix(mask_buf[kl], m); if(kl >= 0 && kl < len) mask_buf[kl] = mask_mix(mask_buf[kl], m);
if(kr >= 0 && kr < len) mask_buf[kr] = mask_mix(mask_buf[kr], m); if(kr >= 0 && kr < len) mask_buf[kr] = mask_mix(mask_buf[kr], m);
kl--; kl--;
@ -1013,14 +1013,14 @@ static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t ab
* the circle still has parts on the next one*/ * the circle still has parts on the next one*/
if(y_prev.f) { if(y_prev.f) {
m = (y_prev.f * x1.f) >> 9; m = (y_prev.f * x1.f) >> 9;
if(p->inv) m = 255 - m; if(p->cfg.outer) m = 255 - m;
if(kl >= 0 && kl < len) mask_buf[kl] = mask_mix(mask_buf[kl], m); if(kl >= 0 && kl < len) mask_buf[kl] = mask_mix(mask_buf[kl], m);
if(kr >= 0 && kr < len) mask_buf[kr] = mask_mix(mask_buf[kr], m); if(kr >= 0 && kr < len) mask_buf[kr] = mask_mix(mask_buf[kr], m);
kl--; kl--;
kr++; kr++;
} }
if(p->inv == 0) { if(p->cfg.outer == 0) {
kl++; kl++;
if(kl > len) { if(kl > len) {
return LV_DRAW_MASK_RES_FULL_TRANSP; return LV_DRAW_MASK_RES_FULL_TRANSP;
@ -1039,42 +1039,40 @@ static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t ab
} }
static lv_draw_mask_res_t lv_draw_mask_fade(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_param_t * param) static lv_draw_mask_res_t lv_draw_mask_fade(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_fade_param_t * p)
{ {
lv_draw_mask_fade_param_t * p = &param->fade; if(abs_y < p->cfg.coords.y1) return LV_DRAW_MASK_RES_FULL_COVER;
if(abs_y > p->cfg.coords.y2) return LV_DRAW_MASK_RES_FULL_COVER;
if(abs_x + len < p->cfg.coords.x1) return LV_DRAW_MASK_RES_FULL_COVER;
if(abs_x > p->cfg.coords.x2) return LV_DRAW_MASK_RES_FULL_COVER;
if(abs_y < p->coords.y1) return LV_DRAW_MASK_RES_FULL_COVER; if(abs_x + len > p->cfg.coords.x2) len -= abs_x + len - p->cfg.coords.x2 - 1;
if(abs_y > p->coords.y2) return LV_DRAW_MASK_RES_FULL_COVER;
if(abs_x + len < p->coords.x1) return LV_DRAW_MASK_RES_FULL_COVER;
if(abs_x > p->coords.x2) return LV_DRAW_MASK_RES_FULL_COVER;
if(abs_x + len > p->coords.x2) len -= abs_x + len - p->coords.x2 - 1; if(abs_x < p->cfg.coords.x1) {
if(abs_x < p->coords.x1) {
lv_coord_t x_ofs = 0; lv_coord_t x_ofs = 0;
x_ofs = p->coords.x1 - abs_x; x_ofs = p->cfg.coords.x1 - abs_x;
len -= x_ofs; len -= x_ofs;
mask_buf += x_ofs; mask_buf += x_ofs;
} }
lv_coord_t i; lv_coord_t i;
if(abs_y <= p->y_top) { if(abs_y <= p->cfg.y_top) {
for(i = 0; i < len; i++) { for(i = 0; i < len; i++) {
mask_buf[i] = mask_mix(mask_buf[i], p->opa_top); mask_buf[i] = mask_mix(mask_buf[i], p->cfg.opa_top);
} }
return LV_DRAW_MASK_RES_CHANGED; return LV_DRAW_MASK_RES_CHANGED;
} else if(abs_y >= p->y_bottom) { } else if(abs_y >= p->cfg.y_bottom) {
for(i = 0; i < len; i++) { for(i = 0; i < len; i++) {
mask_buf[i] = mask_mix(mask_buf[i], p->opa_bottom); mask_buf[i] = mask_mix(mask_buf[i], p->cfg.opa_bottom);
} }
return LV_DRAW_MASK_RES_CHANGED; return LV_DRAW_MASK_RES_CHANGED;
} else { } else {
/*Calculate the opa proportionally*/ /*Calculate the opa proportionally*/
int16_t opa_diff = p->opa_bottom - p->opa_top; int16_t opa_diff = p->cfg.opa_bottom - p->cfg.opa_top;
lv_coord_t y_diff = p->y_bottom - p->y_top + 1; lv_coord_t y_diff = p->cfg.y_bottom - p->cfg.y_top + 1;
lv_opa_t opa_act = (int32_t)((int32_t)(abs_y - p->y_top) * opa_diff) / y_diff; lv_opa_t opa_act = (int32_t)((int32_t)(abs_y - p->cfg.y_top) * opa_diff) / y_diff;
opa_act += p->opa_top; opa_act += p->cfg.opa_top;
for(i = 0; i < len; i++) { for(i = 0; i < len; i++) {
mask_buf[i] = mask_mix(mask_buf[i], opa_act); mask_buf[i] = mask_mix(mask_buf[i], opa_act);
@ -1086,30 +1084,28 @@ static lv_draw_mask_res_t lv_draw_mask_fade(lv_opa_t * mask_buf, lv_coord_t abs_
return LV_DRAW_MASK_RES_FULL_COVER; return LV_DRAW_MASK_RES_FULL_COVER;
} }
static lv_draw_mask_res_t lv_draw_mask_map(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_param_t * param) static lv_draw_mask_res_t lv_draw_mask_map(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, lv_draw_mask_map_param_t * p)
{ {
lv_draw_mask_map_param_t * p = &param->map;
/*Handle out of the mask cases*/ /*Handle out of the mask cases*/
if(abs_y < p->coords.y1) return LV_DRAW_MASK_RES_FULL_COVER; if(abs_y < p->cfg.coords.y1) return LV_DRAW_MASK_RES_FULL_COVER;
if(abs_y > p->coords.y2) return LV_DRAW_MASK_RES_FULL_COVER; if(abs_y > p->cfg.coords.y2) return LV_DRAW_MASK_RES_FULL_COVER;
if(abs_x + len < p->coords.x1) return LV_DRAW_MASK_RES_FULL_COVER; if(abs_x + len < p->cfg.coords.x1) return LV_DRAW_MASK_RES_FULL_COVER;
if(abs_x > p->coords.x2) return LV_DRAW_MASK_RES_FULL_COVER; if(abs_x > p->cfg.coords.x2) return LV_DRAW_MASK_RES_FULL_COVER;
/*Got to the current row in the map*/ /*Got to the current row in the map*/
const lv_opa_t * map_tmp = p->map; const lv_opa_t * map_tmp = p->cfg.map;
map_tmp += (abs_y - p->coords.y1) * lv_area_get_width(&p-> coords); map_tmp += (abs_y - p->cfg.coords.y1) * lv_area_get_width(&p->cfg.coords);
if(abs_x + len > p->coords.x2) len -= abs_x + len - p->coords.x2 - 1; if(abs_x + len > p->cfg.coords.x2) len -= abs_x + len - p->cfg.coords.x2 - 1;
if(abs_x < p->coords.x1) { if(abs_x < p->cfg.coords.x1) {
lv_coord_t x_ofs = 0; lv_coord_t x_ofs = 0;
x_ofs = p->coords.x1 - abs_x; x_ofs = p->cfg.coords.x1 - abs_x;
len -= x_ofs; len -= x_ofs;
mask_buf += x_ofs; mask_buf += x_ofs;
} else { } else {
map_tmp += (abs_x - p->coords.x1); map_tmp += (abs_x - p->cfg.coords.x1);
} }
lv_coord_t i; lv_coord_t i;

View File

@ -36,6 +36,16 @@ enum {
typedef uint8_t lv_draw_mask_res_t; typedef uint8_t lv_draw_mask_res_t;
enum {
LV_DRAW_MASK_TYPE_LINE,
LV_DRAW_MASK_TYPE_ANGLE,
LV_DRAW_MASK_TYPE_RADIUS,
LV_DRAW_MASK_TYPE_FADE,
LV_DRAW_MASK_TYPE_MAP,
};
typedef uint8_t lv_draw_mask_type_t;
enum { enum {
LV_DRAW_MASK_LINE_SIDE_LEFT = 0, LV_DRAW_MASK_LINE_SIDE_LEFT = 0,
LV_DRAW_MASK_LINE_SIDE_RIGHT, LV_DRAW_MASK_LINE_SIDE_RIGHT,
@ -43,18 +53,33 @@ enum {
LV_DRAW_MASK_LINE_SIDE_BOTTOM, LV_DRAW_MASK_LINE_SIDE_BOTTOM,
}; };
union _lv_draw_mask_param_t; typedef lv_draw_mask_res_t (*lv_draw_mask_cb_t)(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, void * p);
typedef lv_draw_mask_res_t (*lv_draw_mask_cb_t)(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, union _lv_draw_mask_param_t * p);
typedef uint8_t lv_draw_mask_line_side_t; typedef uint8_t lv_draw_mask_line_side_t;
typedef struct { typedef struct {
/*The first element must be the callback*/
lv_draw_mask_cb_t cb; lv_draw_mask_cb_t cb;
lv_draw_mask_type_t type;
}lv_draw_mask_common_dsc_t;
typedef struct {
/*The first element must be the common descriptor*/
lv_draw_mask_common_dsc_t dsc;
struct {
/*First point */
lv_point_t p1;
/*Second point*/
lv_point_t p2;
/*Which side to keep?*/
lv_draw_mask_line_side_t side :2;
}cfg;
/*A point of the line*/
lv_point_t origo; lv_point_t origo;
/* X / (1024*Y) steepness (X is 0..1023 range). What is the change of X in 1024 Y?*/ /* X / (1024*Y) steepness (X is 0..1023 range). What is the change of X in 1024 Y?*/
int32_t xy_steep; int32_t xy_steep;
@ -67,11 +92,9 @@ typedef struct {
/*Steepness in 1 px in 0..255 range. Used only by flat lines. */ /*Steepness in 1 px in 0..255 range. Used only by flat lines. */
int32_t spx; int32_t spx;
/*1: It's a flat line? (Neare to horizontal)*/ /*1: It's a flat line? (Near to horizontal)*/
uint8_t flat :1; uint8_t flat :1;
/*Which side to keep?*/
lv_draw_mask_line_side_t side :2;
/* Invert the mask. The default is: Keep the left part. /* Invert the mask. The default is: Keep the left part.
* It is used to select left/right/top/bottom*/ * It is used to select left/right/top/bottom*/
@ -79,52 +102,57 @@ typedef struct {
}lv_draw_mask_line_param_t; }lv_draw_mask_line_param_t;
typedef struct { typedef struct {
lv_draw_mask_cb_t cb; /*The first element must be the callback*/ /*The first element must be the common descriptor*/
lv_point_t vertex; lv_draw_mask_common_dsc_t dsc;
lv_coord_t start_angle;
lv_coord_t end_angle; struct {
lv_point_t vertex_p;
lv_coord_t start_angle;
lv_coord_t end_angle;
}cfg;
lv_draw_mask_line_param_t start_line; lv_draw_mask_line_param_t start_line;
lv_draw_mask_line_param_t end_line; lv_draw_mask_line_param_t end_line;
uint16_t delta_deg; uint16_t delta_deg;
}lv_draw_mask_angle_param_t; }lv_draw_mask_angle_param_t;
typedef struct { typedef struct {
lv_draw_mask_cb_t cb; /*The first element must be the callback*/ /*The first element must be the common descriptor*/
lv_draw_mask_common_dsc_t dsc;
lv_area_t rect; struct {
lv_coord_t radius; lv_area_t rect;
lv_coord_t radius;
/* Invert the mask. 0: Keep the pixels inside.*/
uint8_t outer:1;
}cfg;
/* Invert the mask. The default is: Keep the are inside.*/
uint8_t inv:1;
}lv_draw_mask_radius_param_t; }lv_draw_mask_radius_param_t;
typedef struct { typedef struct {
lv_draw_mask_cb_t cb; /*The first element must be the callback*/ /*The first element must be the common descriptor*/
lv_draw_mask_common_dsc_t dsc;
lv_area_t coords; struct {
lv_coord_t y_top; lv_area_t coords;
lv_coord_t y_bottom; lv_coord_t y_top;
lv_opa_t opa_top; lv_coord_t y_bottom;
lv_opa_t opa_bottom; lv_opa_t opa_top;
lv_opa_t opa_bottom;
}cfg;
}lv_draw_mask_fade_param_t; }lv_draw_mask_fade_param_t;
typedef struct _lv_draw_mask_map_param_t { typedef struct _lv_draw_mask_map_param_t {
lv_draw_mask_cb_t cb; /*The first element must be the callback*/ /*The first element must be the common descriptor*/
lv_draw_mask_common_dsc_t dsc;
lv_area_t coords; struct {
const lv_opa_t * map; lv_area_t coords;
const lv_opa_t * map;
}cfg;
}lv_draw_mask_map_param_t; }lv_draw_mask_map_param_t;
typedef union _lv_draw_mask_param_t {
lv_draw_mask_line_param_t line;
lv_draw_mask_radius_param_t radius;
lv_draw_mask_angle_param_t angle;
lv_draw_mask_fade_param_t fade;
lv_draw_mask_map_param_t map;
}lv_draw_mask_param_t;
/********************** /**********************
* GLOBAL PROTOTYPES * GLOBAL PROTOTYPES
**********************/ **********************/
@ -135,10 +163,10 @@ typedef union _lv_draw_mask_param_t {
* @param custom_id a custom pointer to identify the mask. Used in `lv_draw_mask_remove_custom`. * @param custom_id a custom pointer to identify the mask. Used in `lv_draw_mask_remove_custom`.
* @return the an integer, the ID of the mask. Can be used in `lv_draw_mask_remove_id`. * @return the an integer, the ID of the mask. Can be used in `lv_draw_mask_remove_id`.
*/ */
int16_t lv_draw_mask_add(lv_draw_mask_param_t * param, void * custom_id); int16_t lv_draw_mask_add(void * param, void * custom_id);
/** /**
* Apply the added buffers on a line. Used internally by the library's drawing routins. * Apply the added buffers on a line. Used internally by the library's drawing routines.
* @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`. * @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`.
* @param abs_x absolute X coordinate where the line to calculate start * @param abs_x absolute X coordinate where the line to calculate start
* @param abs_y absolute Y coordinate where the line to calculate start * @param abs_y absolute Y coordinate where the line to calculate start
@ -156,7 +184,7 @@ lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_
* @return the parameter of the removed mask. * @return the parameter of the removed mask.
* If more masks have `custom_id` ID then the last mask's parameter will be returned * If more masks have `custom_id` ID then the last mask's parameter will be returned
*/ */
lv_draw_mask_param_t * lv_draw_mask_remove_id(int16_t id); void * lv_draw_mask_remove_id(int16_t id);
/** /**
* Remove all mask with a given custom ID * Remove all mask with a given custom ID
@ -164,7 +192,7 @@ lv_draw_mask_param_t * lv_draw_mask_remove_id(int16_t id);
* @return return the parameter of the removed mask. * @return return the parameter of the removed mask.
* If more masks have `custom_id` ID then the last mask's parameter will be returned * If more masks have `custom_id` ID then the last mask's parameter will be returned
*/ */
lv_draw_mask_param_t * lv_draw_mask_remove_custom(void * custom_id); void * lv_draw_mask_remove_custom(void * custom_id);
/** /**
* Count the currently added masks * Count the currently added masks
@ -183,7 +211,7 @@ uint8_t lv_draw_mask_get_cnt(void);
* With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept * With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept
* With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept * With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept
*/ */
void lv_draw_mask_line_points_init(lv_draw_mask_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x, lv_coord_t p2y, lv_draw_mask_line_side_t side); void lv_draw_mask_line_points_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x, lv_coord_t p2y, lv_draw_mask_line_side_t side);
/** /**
*Initialize a line mask from a point and an angle. *Initialize a line mask from a point and an angle.
@ -195,7 +223,7 @@ void lv_draw_mask_line_points_init(lv_draw_mask_param_t * param, lv_coord_t p1x,
* With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept * With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept
* With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept * With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept
*/ */
void lv_draw_mask_line_angle_init(lv_draw_mask_param_t * param, lv_coord_t p1x, lv_coord_t py, int16_t angle, lv_draw_mask_line_side_t side); void lv_draw_mask_line_angle_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t py, int16_t angle, lv_draw_mask_line_side_t side);
/** /**
* Initialize an angle mask. * Initialize an angle mask.
@ -205,7 +233,7 @@ void lv_draw_mask_line_angle_init(lv_draw_mask_param_t * param, lv_coord_t p1x,
* @param start_angle start angle in degrees. 0 deg on the right, 90 deg, on the bottom * @param start_angle start angle in degrees. 0 deg on the right, 90 deg, on the bottom
* @param end_angle end angle * @param end_angle end angle
*/ */
void lv_draw_mask_angle_init(lv_draw_mask_param_t * param, lv_coord_t vertex_x, lv_coord_t vertex_y, lv_coord_t start_angle, lv_coord_t end_angle); void lv_draw_mask_angle_init(lv_draw_mask_angle_param_t * param, lv_coord_t vertex_x, lv_coord_t vertex_y, lv_coord_t start_angle, lv_coord_t end_angle);
/** /**
* Initialize a fade mask. * Initialize a fade mask.
@ -214,7 +242,7 @@ void lv_draw_mask_angle_init(lv_draw_mask_param_t * param, lv_coord_t vertex_x,
* @param radius radius of the rectangle * @param radius radius of the rectangle
* @param inv: true: keep the pixels inside teh rectangle; keep teh pixels outside of the rectangle * @param inv: true: keep the pixels inside teh rectangle; keep teh pixels outside of the rectangle
*/ */
void lv_draw_mask_radius_init(lv_draw_mask_param_t * param, const lv_area_t * rect, lv_coord_t radius, bool inv); void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area_t * rect, lv_coord_t radius, bool inv);
/** /**
* Initialize a fade mask. * Initialize a fade mask.
@ -225,7 +253,7 @@ void lv_draw_mask_radius_init(lv_draw_mask_param_t * param, const lv_area_t * re
* @param opa_bottom opacity at the bottom * @param opa_bottom opacity at the bottom
* @param y_bottom at which coordinate reach `opa_bottom`. * @param y_bottom at which coordinate reach `opa_bottom`.
*/ */
void lv_draw_mask_fade_init(lv_draw_mask_param_t * param, lv_area_t * coords, lv_opa_t opa_top, lv_coord_t y_top, lv_opa_t opa_bottom, lv_coord_t y_bottom); void lv_draw_mask_fade_init(lv_draw_mask_fade_param_t * param, lv_area_t * coords, lv_opa_t opa_top, lv_coord_t y_top, lv_opa_t opa_bottom, lv_coord_t y_bottom);
/** /**
* Initialize a map mask. * Initialize a map mask.
@ -233,7 +261,7 @@ void lv_draw_mask_fade_init(lv_draw_mask_param_t * param, lv_area_t * coords, lv
* @param coords coordinates of the map (absolute coordinates) * @param coords coordinates of the map (absolute coordinates)
* @param map array of bytes with the mask values * @param map array of bytes with the mask values
*/ */
void lv_draw_mask_map_init(lv_draw_mask_param_t * param, lv_area_t * coords, const lv_opa_t * map); void lv_draw_mask_map_init(lv_draw_mask_map_param_t * param, lv_area_t * coords, const lv_opa_t * map);
/********************** /**********************
* MACROS * MACROS

View File

@ -162,7 +162,7 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, const lv_s
} }
/*More complex case: there is a radius, gradient or mask.*/ /*More complex case: there is a radius, gradient or mask.*/
else { else {
lv_draw_mask_param_t mask_rout_param; lv_draw_mask_radius_param_t mask_rout_param;
if(rout > 0) { if(rout > 0) {
lv_draw_mask_radius_init(&mask_rout_param, &coords_bg, rout, false); lv_draw_mask_radius_init(&mask_rout_param, &coords_bg, rout, false);
mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL);
@ -318,7 +318,7 @@ static void draw_border(const lv_area_t * coords, const lv_area_t * clip, const
if(rout > short_side >> 1) rout = short_side >> 1; if(rout > short_side >> 1) rout = short_side >> 1;
/*Get the outer area*/ /*Get the outer area*/
lv_draw_mask_param_t mask_rout_param; lv_draw_mask_radius_param_t mask_rout_param;
if(rout > 0) { if(rout > 0) {
lv_draw_mask_radius_init(&mask_rout_param, coords, rout, false); lv_draw_mask_radius_init(&mask_rout_param, coords, rout, false);
mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL);
@ -338,7 +338,7 @@ static void draw_border(const lv_area_t * coords, const lv_area_t * clip, const
area_small.y2 -= ((style->body.border.part & LV_BORDER_PART_BOTTOM) ? border_width : - (border_width + rout)); area_small.y2 -= ((style->body.border.part & LV_BORDER_PART_BOTTOM) ? border_width : - (border_width + rout));
/*Create inner the mask*/ /*Create inner the mask*/
lv_draw_mask_param_t mask_rin_param; lv_draw_mask_radius_param_t mask_rin_param;
lv_draw_mask_radius_init(&mask_rin_param, &area_small, rout - border_width, true); lv_draw_mask_radius_init(&mask_rin_param, &area_small, rout - border_width, true);
int16_t mask_rin_id = lv_draw_mask_add(&mask_rin_param, NULL); int16_t mask_rin_id = lv_draw_mask_add(&mask_rin_param, NULL);
@ -569,7 +569,7 @@ static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, const
lv_draw_mask_res_t mask_res; lv_draw_mask_res_t mask_res;
lv_opa_t * mask_buf = lv_draw_buf_get(lv_area_get_width(&sh_rect_area)); lv_opa_t * mask_buf = lv_draw_buf_get(lv_area_get_width(&sh_rect_area));
lv_draw_mask_param_t mask_rout_param; lv_draw_mask_radius_param_t mask_rout_param;
lv_draw_mask_radius_init(&mask_rout_param, &bg_coords, r_bg, true); lv_draw_mask_radius_init(&mask_rout_param, &bg_coords, r_bg, true);
int16_t mask_rout_id = LV_MASK_ID_INV; int16_t mask_rout_id = LV_MASK_ID_INV;
@ -879,7 +879,7 @@ static void shadow_draw_corner_buf(const lv_area_t * coords, lv_opa_t * sh_buf,
sh_area.x1 = sh_area.x2 - lv_area_get_width(coords); sh_area.x1 = sh_area.x2 - lv_area_get_width(coords);
sh_area.y2 = sh_area.y1 + lv_area_get_height(coords); sh_area.y2 = sh_area.y1 + lv_area_get_height(coords);
lv_draw_mask_param_t mask_param; lv_draw_mask_radius_param_t mask_param;
lv_draw_mask_radius_init(&mask_param, &sh_area, r, false); lv_draw_mask_radius_init(&mask_param, &sh_area, r, false);
#if SHADOW_ENHANCE #if SHADOW_ENHANCE
@ -897,7 +897,7 @@ static void shadow_draw_corner_buf(const lv_area_t * coords, lv_opa_t * sh_buf,
uint16_t * sh_ups_tmp_buf = sh_ups_buf; uint16_t * sh_ups_tmp_buf = sh_ups_buf;
for(y = 0; y < size; y++) { for(y = 0; y < size; y++) {
memset(mask_line, 0xFF, size); memset(mask_line, 0xFF, size);
mask_res = mask_param.radius.cb(mask_line, 0, y, size, &mask_param); mask_res = mask_param.dsc.cb(mask_line, 0, y, size, &mask_param);
if(mask_res == LV_DRAW_MASK_RES_FULL_TRANSP) { if(mask_res == LV_DRAW_MASK_RES_FULL_TRANSP) {
memset(sh_ups_tmp_buf, 0x00, size * sizeof(sh_ups_buf[0])); memset(sh_ups_tmp_buf, 0x00, size * sizeof(sh_ups_buf[0]));
} else { } else {

View File

@ -85,8 +85,8 @@ void lv_draw_polygon(const lv_point_t * points, uint16_t point_cnt, const lv_are
} }
} }
lv_draw_mask_param_t * mp = lv_draw_buf_get(sizeof(lv_draw_mask_param_t) * point_cnt); lv_draw_mask_line_param_t * mp = lv_draw_buf_get(sizeof(lv_draw_mask_line_param_t) * point_cnt);
lv_draw_mask_param_t * mp_next = mp; lv_draw_mask_line_param_t * mp_next = mp;
int32_t i_prev_left = y_min_i; int32_t i_prev_left = y_min_i;
int32_t i_prev_right = y_min_i; int32_t i_prev_right = y_min_i;

View File

@ -550,7 +550,7 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area, lv_design_mo
mask_indic_max_area.y2 -= style_indic->body.padding.bottom; mask_indic_max_area.y2 -= style_indic->body.padding.bottom;
/*Create a mask to the current indicator area. This is see only this part from the whole gradient.*/ /*Create a mask to the current indicator area. This is see only this part from the whole gradient.*/
lv_draw_mask_param_t mask_indic_param; lv_draw_mask_radius_param_t mask_indic_param;
lv_draw_mask_radius_init(&mask_indic_param, &ext->indic_area, style_indic->body.radius, false); lv_draw_mask_radius_init(&mask_indic_param, &ext->indic_area, style_indic->body.radius, false);
int16_t mask_indic_id = lv_draw_mask_add(&mask_indic_param, NULL); int16_t mask_indic_id = lv_draw_mask_add(&mask_indic_param, NULL);

View File

@ -1115,7 +1115,7 @@ static void lv_chart_draw_areas(lv_obj_t * chart, const lv_area_t * mask)
lv_style_copy(&style, &lv_style_plain); lv_style_copy(&style, &lv_style_plain);
int16_t mask_fade_id = LV_MASK_ID_INV; int16_t mask_fade_id = LV_MASK_ID_INV;
lv_draw_mask_param_t mask_fade_p; lv_draw_mask_fade_param_t mask_fade_p;
if(ext->type & LV_CHART_TYPE_AREA_FADED) { if(ext->type & LV_CHART_TYPE_AREA_FADED) {
lv_draw_mask_fade_init(&mask_fade_p, &chart->coords, LV_OPA_COVER, chart->coords.y1 + (h >> 2), LV_OPA_TRANSP, chart->coords.y2 - (h >> 2)); lv_draw_mask_fade_init(&mask_fade_p, &chart->coords, LV_OPA_COVER, chart->coords.y1 + (h >> 2), LV_OPA_TRANSP, chart->coords.y2 - (h >> 2));
mask_fade_id = lv_draw_mask_add(&mask_fade_p, NULL); mask_fade_id = lv_draw_mask_add(&mask_fade_p, NULL);
@ -1150,7 +1150,7 @@ static void lv_chart_draw_areas(lv_obj_t * chart, const lv_area_t * mask)
if(ser->points[p_prev] != LV_CHART_POINT_DEF && ser->points[p_act] != LV_CHART_POINT_DEF) { if(ser->points[p_prev] != LV_CHART_POINT_DEF && ser->points[p_act] != LV_CHART_POINT_DEF) {
int16_t mask_line_id; int16_t mask_line_id;
lv_draw_mask_param_t mask_line_p; lv_draw_mask_line_param_t mask_line_p;
lv_draw_mask_line_points_init(&mask_line_p, p1.x, p1.y, p2.x, p2.y, LV_DRAW_MASK_LINE_SIDE_BOTTOM); lv_draw_mask_line_points_init(&mask_line_p, p1.x, p1.y, p2.x, p2.y, LV_DRAW_MASK_LINE_SIDE_BOTTOM);
mask_line_id = lv_draw_mask_add(&mask_line_p, NULL); mask_line_id = lv_draw_mask_add(&mask_line_p, NULL);

View File

@ -8,6 +8,7 @@
*********************/ *********************/
#include "lv_objmask.h" #include "lv_objmask.h"
#include "../lv_core/lv_debug.h" #include "../lv_core/lv_debug.h"
#include "../lv_draw/lv_draw.h"
#if defined(LV_USE_OBJMASK) && LV_USE_OBJMASK != 0 #if defined(LV_USE_OBJMASK) && LV_USE_OBJMASK != 0
@ -91,14 +92,34 @@ lv_obj_t * lv_objmask_create(lv_obj_t * par, const lv_obj_t * copy)
* Add/remove functions * Add/remove functions
*=====================*/ *=====================*/
void lv_objmask_add_mask(lv_obj_t * objmask, lv_draw_mask_param_t * param, uint8_t id) void lv_objmask_add_mask(lv_obj_t * objmask, void * param, uint8_t id)
{ {
lv_objmask_ext_t * ext = lv_obj_get_ext_attr(objmask); lv_objmask_ext_t * ext = lv_obj_get_ext_attr(objmask);
lv_objmask_mask_t * m = lv_ll_ins_head(&ext->mask_ll); lv_draw_mask_common_dsc_t * dsc = param;
uint16_t param_size;
switch(dsc->type) {
case LV_DRAW_MASK_TYPE_LINE: param_size = sizeof(lv_draw_mask_line_param_t); break;
case LV_DRAW_MASK_TYPE_ANGLE: param_size = sizeof(lv_draw_mask_angle_param_t); break;
case LV_DRAW_MASK_TYPE_RADIUS: param_size = sizeof(lv_draw_mask_radius_param_t); break;
case LV_DRAW_MASK_TYPE_FADE: param_size = sizeof(lv_draw_mask_fade_param_t); break;
case LV_DRAW_MASK_TYPE_MAP: param_size = sizeof(lv_draw_mask_map_param_t); break;
default: param_size = 0;
}
lv_objmask_mask_t * m = lv_ll_ins_head(&ext->mask_ll);
m->param = lv_mem_alloc(param_size);
LV_ASSERT_MEM(m->param);
if(m == NULL) return;
memcpy(m->param, param, param_size);
memcpy(&m->param, param, sizeof(lv_draw_mask_param_t));
m->id = id; m->id = id;
} }
/*===================== /*=====================
@ -146,16 +167,89 @@ static lv_design_res_t lv_objmask_design(lv_obj_t * objmask, const lv_area_t * c
ancestor_design(objmask, clip_area, mode); ancestor_design(objmask, clip_area, mode);
lv_objmask_ext_t * ext = lv_obj_get_ext_attr(objmask); lv_objmask_ext_t * ext = lv_obj_get_ext_attr(objmask);
lv_coord_t xofs = objmask->coords.x1;
lv_coord_t yofs = objmask->coords.y1;
lv_objmask_mask_t * m; lv_objmask_mask_t * m;
LV_LL_READ(ext->mask_ll, m) { LV_LL_READ(ext->mask_ll, m) {
lv_draw_mask_add(&m->param, &ext->mask_ll); lv_draw_mask_common_dsc_t * dsc = m->param;
if(dsc->type == LV_DRAW_MASK_TYPE_LINE) {
lv_draw_mask_line_param_t * p_ori = m->param;
lv_draw_mask_line_param_t * p_new = lv_draw_buf_get(sizeof(lv_draw_mask_line_param_t));
lv_draw_mask_line_points_init(p_new, p_ori->cfg.p1.x + xofs, p_ori->cfg.p1.y + yofs,
p_ori->cfg.p2.x + xofs, p_ori->cfg.p2.y + yofs,
p_ori->cfg.side);
lv_draw_mask_add(p_new, m->param);
}
else if(dsc->type == LV_DRAW_MASK_TYPE_ANGLE) {
lv_draw_mask_angle_param_t * p_ori = m->param;
lv_draw_mask_angle_param_t * p_new = lv_draw_buf_get(sizeof(lv_draw_mask_angle_param_t));
lv_draw_mask_angle_init(p_new, p_ori->cfg.vertex_p.x + xofs, p_ori->cfg.vertex_p.y + yofs,
p_ori->cfg.start_angle, p_ori->cfg.end_angle);
lv_draw_mask_add(p_new, m->param);
}
else if(dsc->type == LV_DRAW_MASK_TYPE_RADIUS) {
lv_draw_mask_radius_param_t * p_ori = m->param;
lv_draw_mask_radius_param_t * p_new = lv_draw_buf_get(sizeof(lv_draw_mask_radius_param_t));
lv_area_t rect;
rect.x1 = p_ori->cfg.rect.x1 + xofs;
rect.y1 = p_ori->cfg.rect.y1 + yofs;
rect.x2 = p_ori->cfg.rect.x2 + xofs;
rect.y2 = p_ori->cfg.rect.y2 + yofs;
lv_draw_mask_radius_init(p_new, &rect, p_ori->cfg.radius, p_ori->cfg.outer);
lv_draw_mask_add(p_new, m->param);
}
else if(dsc->type == LV_DRAW_MASK_TYPE_FADE) {
lv_draw_mask_fade_param_t * p_ori = m->param;
lv_draw_mask_fade_param_t * p_new = lv_draw_buf_get(sizeof(lv_draw_mask_fade_param_t));
lv_area_t rect;
rect.x1 = p_ori->cfg.coords.x1 + xofs;
rect.y1 = p_ori->cfg.coords.y1 + yofs;
rect.x2 = p_ori->cfg.coords.x2 + xofs;
rect.y2 = p_ori->cfg.coords.y2 + yofs;
lv_draw_mask_fade_init(p_new, &rect, p_ori->cfg.opa_top, p_ori->cfg.y_top + yofs,
p_ori->cfg.opa_bottom, p_ori->cfg.y_bottom + yofs);
lv_draw_mask_add(p_new, m->param);
}
else if(dsc->type == LV_DRAW_MASK_TYPE_MAP) {
lv_draw_mask_map_param_t * p_ori = m->param;
lv_draw_mask_map_param_t * p_new = lv_draw_buf_get(sizeof(lv_draw_mask_map_param_t));
lv_area_t rect;
rect.x1 = p_ori->cfg.coords.x1 + xofs;
rect.y1 = p_ori->cfg.coords.y1 + yofs;
rect.x2 = p_ori->cfg.coords.x2 + xofs;
rect.y2 = p_ori->cfg.coords.y2 + yofs;
lv_draw_mask_map_init(p_new, &rect, p_ori->cfg.map);
lv_draw_mask_add(p_new, m->param);
}
} }
} }
/*Post draw when the children are drawn*/ /*Post draw when the children are drawn*/
else if(mode == LV_DESIGN_DRAW_POST) { else if(mode == LV_DESIGN_DRAW_POST) {
lv_objmask_ext_t * ext = lv_obj_get_ext_attr(objmask); lv_objmask_ext_t * ext = lv_obj_get_ext_attr(objmask);
lv_draw_mask_remove_custom(&ext->mask_ll);
lv_objmask_mask_t * m;
LV_LL_READ(ext->mask_ll, m) {
void * param;
param = lv_draw_mask_remove_custom(m->param);
lv_draw_buf_release(param);
}
} }
return LV_DESIGN_RES_OK; return LV_DESIGN_RES_OK;
@ -178,14 +272,14 @@ static lv_res_t lv_objmask_signal(lv_obj_t * objmask, lv_signal_t sign, void * p
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
if(sign == LV_SIGNAL_CLEANUP) { if(sign == LV_SIGNAL_CLEANUP) {
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/ lv_objmask_ext_t * ext = lv_obj_get_ext_attr(objmask);
} else if(sign == LV_SIGNAL_GET_TYPE) { lv_objmask_mask_t * i;
lv_obj_type_t * buf = param; LV_LL_READ(ext->mask_ll, i) {
uint8_t i; if(i->param) {
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/ lv_mem_free(i->param);
if(buf->type[i] == NULL) break; i->param = NULL;
}
} }
buf->type[i] = "lv_objmask";
} }
return res; return res;

View File

@ -33,8 +33,7 @@ extern "C" {
**********************/ **********************/
typedef struct { typedef struct {
lv_draw_mask_param_t param; void * param;
lv_draw_mask_cb_t mask_cb;
uint8_t id; uint8_t id;
}lv_objmask_mask_t; }lv_objmask_mask_t;
@ -68,7 +67,7 @@ lv_obj_t * lv_objmask_create(lv_obj_t * par, const lv_obj_t * copy);
/*====================== /*======================
* Add/remove functions * Add/remove functions
*=====================*/ *=====================*/
void lv_objmask_add_mask(lv_obj_t * objmask, lv_draw_mask_param_t * param, uint8_t id); void lv_objmask_add_mask(lv_obj_t * objmask, void * param, uint8_t id);
/*===================== /*=====================
* Setter functions * Setter functions

View File

@ -706,9 +706,10 @@ static lv_design_res_t lv_page_design(lv_obj_t * page, const lv_area_t * clip_ar
if(style->body.corner_mask) { if(style->body.corner_mask) {
style = lv_page_get_style(page, LV_PAGE_STYLE_BG); style = lv_page_get_style(page, LV_PAGE_STYLE_BG);
lv_draw_mask_param_t * mp = lv_draw_buf_get(sizeof(lv_draw_mask_param_t));; lv_draw_mask_radius_param_t * mp = lv_draw_buf_get(sizeof(lv_draw_mask_radius_param_t));;
lv_draw_mask_radius_init(mp, &page->coords, style->body.radius, false); lv_draw_mask_radius_init(mp, &page->coords, style->body.radius, false);
lv_draw_mask_add(mp, page + 4); /*Add the mask and use `page+8` as custom id. Don't use `page` directly because it might be sued by the user*/
lv_draw_mask_add(mp, page + 8);
} }
} else if(mode == LV_DESIGN_DRAW_POST) { } else if(mode == LV_DESIGN_DRAW_POST) {
/*Draw only a border*/ /*Draw only a border*/
@ -781,8 +782,8 @@ static lv_design_res_t lv_page_design(lv_obj_t * page, const lv_area_t * clip_ar
} }
if(style->body.corner_mask) { if(style->body.corner_mask) {
lv_draw_mask_param_t * mp = lv_draw_mask_remove_custom(page + 4); void * param = lv_draw_mask_remove_custom(page + 8);
lv_draw_buf_release(mp); lv_draw_buf_release(param);
} }
#endif #endif
} }