|
|
|
|
@@ -41,6 +41,7 @@ LV_ATTRIBUTE_FAST_MEM static void shadow_blur_corner(lv_coord_t size, lv_coord_t
|
|
|
|
|
#endif
|
|
|
|
|
static void draw_pattern(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc);
|
|
|
|
|
static void draw_value(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc);
|
|
|
|
|
static void draw_full_border(const lv_area_t * area_inner, const lv_area_t * area_outer, const lv_area_t * clip, lv_coord_t radius, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode);
|
|
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
|
* STATIC VARIABLES
|
|
|
|
|
@@ -370,41 +371,6 @@ LV_ATTRIBUTE_FAST_MEM static void draw_border(const lv_area_t * coords, const lv
|
|
|
|
|
if(dsc->border_width == 0) return;
|
|
|
|
|
if(dsc->border_side == LV_BORDER_SIDE_NONE) return;
|
|
|
|
|
|
|
|
|
|
lv_opa_t opa = dsc->border_opa;
|
|
|
|
|
|
|
|
|
|
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
|
|
|
|
|
|
|
|
|
|
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
|
|
|
|
lv_disp_buf_t * vdb = lv_disp_get_buf(disp);
|
|
|
|
|
|
|
|
|
|
/* Get clipped fill area which is the real draw area.
|
|
|
|
|
* It is always the same or inside `fill_area` */
|
|
|
|
|
lv_area_t draw_area;
|
|
|
|
|
bool is_common;
|
|
|
|
|
is_common = _lv_area_intersect(&draw_area, coords, clip);
|
|
|
|
|
if(is_common == false) return;
|
|
|
|
|
|
|
|
|
|
const lv_area_t * disp_area = &vdb->area;
|
|
|
|
|
|
|
|
|
|
/* Now `draw_area` has absolute coordinates.
|
|
|
|
|
* Make it relative to `disp_area` to simplify draw to `disp_buf`*/
|
|
|
|
|
draw_area.x1 -= disp_area->x1;
|
|
|
|
|
draw_area.y1 -= disp_area->y1;
|
|
|
|
|
draw_area.x2 -= disp_area->x1;
|
|
|
|
|
draw_area.y2 -= disp_area->y1;
|
|
|
|
|
|
|
|
|
|
int32_t draw_area_w = lv_area_get_width(&draw_area);
|
|
|
|
|
|
|
|
|
|
/*Create a mask if there is a radius*/
|
|
|
|
|
lv_opa_t * mask_buf = _lv_mem_buf_get(draw_area_w);
|
|
|
|
|
|
|
|
|
|
uint8_t other_mask_cnt = lv_draw_mask_get_cnt();
|
|
|
|
|
bool simple_mode = true;
|
|
|
|
|
if(other_mask_cnt) simple_mode = false;
|
|
|
|
|
else if(dsc->border_side != LV_BORDER_SIDE_FULL) simple_mode = false;
|
|
|
|
|
|
|
|
|
|
int16_t mask_rout_id = LV_MASK_ID_INV;
|
|
|
|
|
|
|
|
|
|
int32_t coords_w = lv_area_get_width(coords);
|
|
|
|
|
int32_t coords_h = lv_area_get_height(coords);
|
|
|
|
|
|
|
|
|
|
@@ -413,133 +379,73 @@ LV_ATTRIBUTE_FAST_MEM static void draw_border(const lv_area_t * coords, const lv
|
|
|
|
|
int32_t short_side = LV_MATH_MIN(coords_w, coords_h);
|
|
|
|
|
if(rout > short_side >> 1) rout = short_side >> 1;
|
|
|
|
|
|
|
|
|
|
/*Get the outer area*/
|
|
|
|
|
lv_draw_mask_radius_param_t mask_rout_param;
|
|
|
|
|
if(rout > 0) {
|
|
|
|
|
lv_draw_mask_radius_init(&mask_rout_param, coords, rout, false);
|
|
|
|
|
mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*Get the inner radius*/
|
|
|
|
|
int32_t rin = rout - dsc->border_width;
|
|
|
|
|
if(rin < 0) rin = 0;
|
|
|
|
|
|
|
|
|
|
/*Get the inner area*/
|
|
|
|
|
lv_area_t area_small;
|
|
|
|
|
lv_area_copy(&area_small, coords);
|
|
|
|
|
area_small.x1 += ((dsc->border_side & LV_BORDER_SIDE_LEFT) ? dsc->border_width : - (dsc->border_width + rout));
|
|
|
|
|
area_small.x2 -= ((dsc->border_side & LV_BORDER_SIDE_RIGHT) ? dsc->border_width : - (dsc->border_width + rout));
|
|
|
|
|
area_small.y1 += ((dsc->border_side & LV_BORDER_SIDE_TOP) ? dsc->border_width : - (dsc->border_width + rout));
|
|
|
|
|
area_small.y2 -= ((dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? dsc->border_width : - (dsc->border_width + rout));
|
|
|
|
|
lv_area_t area_inner;
|
|
|
|
|
lv_area_copy(&area_inner, coords);
|
|
|
|
|
area_inner.x1 += ((dsc->border_side & LV_BORDER_SIDE_LEFT) ? dsc->border_width : - (dsc->border_width + rout));
|
|
|
|
|
area_inner.x2 -= ((dsc->border_side & LV_BORDER_SIDE_RIGHT) ? dsc->border_width : - (dsc->border_width + rout));
|
|
|
|
|
area_inner.y1 += ((dsc->border_side & LV_BORDER_SIDE_TOP) ? dsc->border_width : - (dsc->border_width + rout));
|
|
|
|
|
area_inner.y2 -= ((dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? dsc->border_width : - (dsc->border_width + rout));
|
|
|
|
|
|
|
|
|
|
/*Create inner the mask*/
|
|
|
|
|
lv_draw_mask_radius_param_t mask_rin_param;
|
|
|
|
|
lv_draw_mask_radius_init(&mask_rin_param, &area_small, rout - dsc->border_width, true);
|
|
|
|
|
int16_t mask_rin_id = lv_draw_mask_add(&mask_rin_param, NULL);
|
|
|
|
|
|
|
|
|
|
int32_t corner_size = LV_MATH_MAX(rout, dsc->border_width - 1);
|
|
|
|
|
|
|
|
|
|
int32_t h;
|
|
|
|
|
lv_draw_mask_res_t mask_res;
|
|
|
|
|
lv_area_t fill_area;
|
|
|
|
|
|
|
|
|
|
lv_color_t color = dsc->border_color;
|
|
|
|
|
lv_blend_mode_t blend_mode = dsc->border_blend_mode;
|
|
|
|
|
|
|
|
|
|
/*Apply some optimization if there is no other mask*/
|
|
|
|
|
if(simple_mode) {
|
|
|
|
|
/*Draw the upper corner area*/
|
|
|
|
|
int32_t upper_corner_end = coords->y1 - disp_area->y1 + corner_size;
|
|
|
|
|
upper_corner_end = LV_MATH_MIN(upper_corner_end, draw_area.y2);
|
|
|
|
|
fill_area.x1 = coords->x1;
|
|
|
|
|
fill_area.x2 = coords->x2;
|
|
|
|
|
fill_area.y1 = disp_area->y1 + draw_area.y1;
|
|
|
|
|
fill_area.y2 = fill_area.y1;
|
|
|
|
|
for(h = draw_area.y1; h <= upper_corner_end; h++) {
|
|
|
|
|
_lv_memset_ff(mask_buf, draw_area_w);
|
|
|
|
|
mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w);
|
|
|
|
|
|
|
|
|
|
lv_area_t fill_area2;
|
|
|
|
|
fill_area2.y1 = fill_area.y1;
|
|
|
|
|
fill_area2.y2 = fill_area.y2;
|
|
|
|
|
|
|
|
|
|
fill_area2.x1 = coords->x1;
|
|
|
|
|
fill_area2.x2 = coords->x1 + rout - 1;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, mask_buf, mask_res, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
/*Draw the top horizontal line*/
|
|
|
|
|
if(fill_area2.y2 < coords->y1 + dsc->border_width) {
|
|
|
|
|
fill_area2.x1 = coords->x1 + rout;
|
|
|
|
|
fill_area2.x2 = coords->x2 - rout;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fill_area2.x1 = coords->x2 - rout + 1;
|
|
|
|
|
fill_area2.x2 = coords->x2;
|
|
|
|
|
|
|
|
|
|
int32_t mask_ofs = (coords->x2 - rout + 1) - (vdb->area.x1 + draw_area.x1);
|
|
|
|
|
if(mask_ofs < 0) mask_ofs = 0;
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, mask_buf + mask_ofs, mask_res, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
fill_area.y1++;
|
|
|
|
|
fill_area.y2++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*Draw the lower corner area */
|
|
|
|
|
int32_t lower_corner_end = coords->y2 - disp_area->y1 - corner_size;
|
|
|
|
|
lower_corner_end = LV_MATH_MAX(lower_corner_end, draw_area.y1);
|
|
|
|
|
if(lower_corner_end <= upper_corner_end) lower_corner_end = upper_corner_end + 1;
|
|
|
|
|
fill_area.y1 = disp_area->y1 + lower_corner_end;
|
|
|
|
|
fill_area.y2 = fill_area.y1;
|
|
|
|
|
for(h = lower_corner_end; h <= draw_area.y2; h++) {
|
|
|
|
|
_lv_memset_ff(mask_buf, draw_area_w);
|
|
|
|
|
mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w);
|
|
|
|
|
|
|
|
|
|
lv_area_t fill_area2;
|
|
|
|
|
fill_area2.x1 = coords->x1;
|
|
|
|
|
fill_area2.x2 = coords->x1 + rout - 1;
|
|
|
|
|
fill_area2.y1 = fill_area.y1;
|
|
|
|
|
fill_area2.y2 = fill_area.y2;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, mask_buf, mask_res, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
/*Draw the bottom horizontal line*/
|
|
|
|
|
if(fill_area2.y2 > coords->y2 - dsc->border_width) {
|
|
|
|
|
fill_area2.x1 = coords->x1 + rout;
|
|
|
|
|
fill_area2.x2 = coords->x2 - rout;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode);
|
|
|
|
|
}
|
|
|
|
|
fill_area2.x1 = coords->x2 - rout + 1;
|
|
|
|
|
fill_area2.x2 = coords->x2;
|
|
|
|
|
|
|
|
|
|
int32_t mask_ofs = (coords->x2 - rout + 1) - (vdb->area.x1 + draw_area.x1);
|
|
|
|
|
if(mask_ofs < 0) mask_ofs = 0;
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, mask_buf + mask_ofs, mask_res, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fill_area.y1++;
|
|
|
|
|
fill_area.y2++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*Draw the left vertical border part*/
|
|
|
|
|
fill_area.y1 = coords->y1 + corner_size + 1;
|
|
|
|
|
fill_area.y2 = coords->y2 - corner_size - 1;
|
|
|
|
|
|
|
|
|
|
fill_area.x1 = coords->x1;
|
|
|
|
|
fill_area.x2 = coords->x1 + dsc->border_width - 1;
|
|
|
|
|
_lv_blend_fill(clip, &fill_area, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
/*Draw the right vertical border*/
|
|
|
|
|
fill_area.x1 = coords->x2 - dsc->border_width + 1;
|
|
|
|
|
fill_area.x2 = coords->x2;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode);
|
|
|
|
|
if(dsc->border_side == LV_BORDER_SIDE_FULL) {
|
|
|
|
|
draw_full_border(&area_inner, coords, clip, dsc->radius, dsc->border_color, dsc->border_opa, dsc->border_blend_mode);
|
|
|
|
|
}
|
|
|
|
|
/*Process line by line if there is other mask too*/
|
|
|
|
|
else {
|
|
|
|
|
lv_opa_t opa = dsc->border_opa;
|
|
|
|
|
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
|
|
|
|
|
|
|
|
|
|
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
|
|
|
|
lv_disp_buf_t * vdb = lv_disp_get_buf(disp);
|
|
|
|
|
|
|
|
|
|
/* Get clipped fill area which is the real draw area.
|
|
|
|
|
* It is always the same or inside `fill_area` */
|
|
|
|
|
lv_area_t draw_area;
|
|
|
|
|
bool is_common;
|
|
|
|
|
is_common = _lv_area_intersect(&draw_area, coords, clip);
|
|
|
|
|
if(is_common == false) return;
|
|
|
|
|
|
|
|
|
|
const lv_area_t * disp_area = &vdb->area;
|
|
|
|
|
|
|
|
|
|
/* Now `draw_area` has absolute coordinates.
|
|
|
|
|
* Make it relative to `disp_area` to simplify draw to `disp_buf`*/
|
|
|
|
|
draw_area.x1 -= disp_area->x1;
|
|
|
|
|
draw_area.y1 -= disp_area->y1;
|
|
|
|
|
draw_area.x2 -= disp_area->x1;
|
|
|
|
|
draw_area.y2 -= disp_area->y1;
|
|
|
|
|
|
|
|
|
|
int32_t draw_area_w = lv_area_get_width(&draw_area);
|
|
|
|
|
|
|
|
|
|
/*Create a mask if there is a radius*/
|
|
|
|
|
lv_opa_t * mask_buf = _lv_mem_buf_get(draw_area_w);
|
|
|
|
|
|
|
|
|
|
uint8_t other_mask_cnt = lv_draw_mask_get_cnt();
|
|
|
|
|
bool simple_mode = true;
|
|
|
|
|
if(other_mask_cnt) simple_mode = false;
|
|
|
|
|
|
|
|
|
|
/*Create mask for the outer area*/
|
|
|
|
|
int16_t mask_rout_id = LV_MASK_ID_INV;
|
|
|
|
|
lv_draw_mask_radius_param_t mask_rout_param;
|
|
|
|
|
if(rout > 0) {
|
|
|
|
|
lv_draw_mask_radius_init(&mask_rout_param, coords, rout, false);
|
|
|
|
|
mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*Create mask for the inner mask*/
|
|
|
|
|
int32_t rin = rout - dsc->border_width;
|
|
|
|
|
if(rin < 0) rin = 0;
|
|
|
|
|
lv_draw_mask_radius_param_t mask_rin_param;
|
|
|
|
|
lv_draw_mask_radius_init(&mask_rin_param, &area_inner, rout - dsc->border_width, true);
|
|
|
|
|
int16_t mask_rin_id = lv_draw_mask_add(&mask_rin_param, NULL);
|
|
|
|
|
|
|
|
|
|
int32_t corner_size = LV_MATH_MAX(rout, dsc->border_width - 1);
|
|
|
|
|
|
|
|
|
|
int32_t h;
|
|
|
|
|
lv_draw_mask_res_t mask_res;
|
|
|
|
|
lv_area_t fill_area;
|
|
|
|
|
|
|
|
|
|
lv_color_t color = dsc->border_color;
|
|
|
|
|
lv_blend_mode_t blend_mode = dsc->border_blend_mode;
|
|
|
|
|
|
|
|
|
|
fill_area.x1 = coords->x1;
|
|
|
|
|
fill_area.x2 = coords->x2;
|
|
|
|
|
fill_area.y1 = disp_area->y1 + draw_area.y1;
|
|
|
|
|
@@ -565,8 +471,8 @@ LV_ATTRIBUTE_FAST_MEM static void draw_border(const lv_area_t * coords, const lv
|
|
|
|
|
|
|
|
|
|
for(h = draw_area.y1; h <= draw_area.y2; h++) {
|
|
|
|
|
if(normal ||
|
|
|
|
|
(top_only && fill_area.y1 <= coords->y1 + corner_size) ||
|
|
|
|
|
(bottom_only && fill_area.y1 >= coords->y2 - corner_size)) {
|
|
|
|
|
(top_only && fill_area.y1 <= coords->y1 + corner_size) ||
|
|
|
|
|
(bottom_only && fill_area.y1 >= coords->y2 - corner_size)) {
|
|
|
|
|
_lv_memset_ff(mask_buf, draw_area_w);
|
|
|
|
|
mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w);
|
|
|
|
|
_lv_blend_fill(clip, &fill_area, color, mask_buf + buf_ofs, mask_res, opa, blend_mode);
|
|
|
|
|
@@ -575,10 +481,10 @@ LV_ATTRIBUTE_FAST_MEM static void draw_border(const lv_area_t * coords, const lv
|
|
|
|
|
fill_area.y2++;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
lv_draw_mask_remove_id(mask_rin_id);
|
|
|
|
|
lv_draw_mask_remove_id(mask_rout_id);
|
|
|
|
|
_lv_mem_buf_release(mask_buf);
|
|
|
|
|
}
|
|
|
|
|
lv_draw_mask_remove_id(mask_rin_id);
|
|
|
|
|
lv_draw_mask_remove_id(mask_rout_id);
|
|
|
|
|
_lv_mem_buf_release(mask_buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LV_ATTRIBUTE_FAST_MEM static inline lv_color_t grad_get(lv_draw_rect_dsc_t * dsc, lv_coord_t s, lv_coord_t i)
|
|
|
|
|
@@ -1235,10 +1141,6 @@ static void draw_outline(const lv_area_t * coords, const lv_area_t * clip, lv_dr
|
|
|
|
|
|
|
|
|
|
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
|
|
|
|
|
|
|
|
|
|
uint8_t other_mask_cnt = lv_draw_mask_get_cnt();
|
|
|
|
|
bool simple_mode = true;
|
|
|
|
|
if(other_mask_cnt) simple_mode = false;
|
|
|
|
|
|
|
|
|
|
/*Get the inner radius*/
|
|
|
|
|
lv_area_t area_inner;
|
|
|
|
|
lv_area_copy(&area_inner, coords);
|
|
|
|
|
@@ -1247,16 +1149,6 @@ static void draw_outline(const lv_area_t * coords, const lv_area_t * clip, lv_dr
|
|
|
|
|
area_inner.x2 += dsc->outline_pad;
|
|
|
|
|
area_inner.y2 += dsc->outline_pad;
|
|
|
|
|
|
|
|
|
|
int32_t inner_w = lv_area_get_width(&area_inner);
|
|
|
|
|
int32_t inner_h = lv_area_get_height(&area_inner);
|
|
|
|
|
|
|
|
|
|
int32_t rin = dsc->radius;
|
|
|
|
|
int32_t short_side = LV_MATH_MIN(inner_w, inner_h);
|
|
|
|
|
if(rin > short_side >> 1) rin = short_side >> 1;
|
|
|
|
|
|
|
|
|
|
/*Get the outer area*/
|
|
|
|
|
int32_t rout = rin + dsc->outline_width;
|
|
|
|
|
|
|
|
|
|
lv_area_t area_outer;
|
|
|
|
|
lv_area_copy(&area_outer, &area_inner);
|
|
|
|
|
|
|
|
|
|
@@ -1265,163 +1157,7 @@ static void draw_outline(const lv_area_t * coords, const lv_area_t * clip, lv_dr
|
|
|
|
|
area_outer.y1 -= dsc->outline_width;
|
|
|
|
|
area_outer.y2 += dsc->outline_width;
|
|
|
|
|
|
|
|
|
|
int32_t coords_out_w = lv_area_get_width(&area_outer);
|
|
|
|
|
int32_t coords_out_h = lv_area_get_height(&area_outer);
|
|
|
|
|
short_side = LV_MATH_MIN(coords_out_w, coords_out_h);
|
|
|
|
|
if(rout > short_side >> 1) rout = short_side >> 1;
|
|
|
|
|
|
|
|
|
|
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
|
|
|
|
lv_disp_buf_t * vdb = lv_disp_get_buf(disp);
|
|
|
|
|
|
|
|
|
|
/* Get clipped fill area which is the real draw area.
|
|
|
|
|
* It is always the same or inside `fill_area` */
|
|
|
|
|
lv_area_t draw_area;
|
|
|
|
|
bool is_common;
|
|
|
|
|
is_common = _lv_area_intersect(&draw_area, &area_outer, clip);
|
|
|
|
|
if(is_common == false) return;
|
|
|
|
|
|
|
|
|
|
const lv_area_t * disp_area = &vdb->area;
|
|
|
|
|
|
|
|
|
|
/* Now `draw_area` has absolute coordinates.
|
|
|
|
|
* Make it relative to `disp_area` to simplify draw to `disp_buf`*/
|
|
|
|
|
draw_area.x1 -= disp_area->x1;
|
|
|
|
|
draw_area.y1 -= disp_area->y1;
|
|
|
|
|
draw_area.x2 -= disp_area->x1;
|
|
|
|
|
draw_area.y2 -= disp_area->y1;
|
|
|
|
|
|
|
|
|
|
int32_t draw_area_w = lv_area_get_width(&draw_area);
|
|
|
|
|
|
|
|
|
|
/*Create inner the mask*/
|
|
|
|
|
lv_draw_mask_radius_param_t mask_rin_param;
|
|
|
|
|
lv_draw_mask_radius_init(&mask_rin_param, &area_inner, rin, true);
|
|
|
|
|
int16_t mask_rin_id = lv_draw_mask_add(&mask_rin_param, NULL);
|
|
|
|
|
|
|
|
|
|
lv_draw_mask_radius_param_t mask_rout_param;
|
|
|
|
|
lv_draw_mask_radius_init(&mask_rout_param, &area_outer, rout, false);
|
|
|
|
|
int16_t mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL);
|
|
|
|
|
|
|
|
|
|
lv_opa_t * mask_buf = _lv_mem_buf_get(draw_area_w);
|
|
|
|
|
|
|
|
|
|
int32_t corner_size = LV_MATH_MAX(rout, dsc->outline_width - 1);
|
|
|
|
|
|
|
|
|
|
int32_t h;
|
|
|
|
|
lv_draw_mask_res_t mask_res;
|
|
|
|
|
lv_area_t fill_area;
|
|
|
|
|
|
|
|
|
|
lv_color_t color = dsc->outline_color;
|
|
|
|
|
lv_blend_mode_t blend_mode = dsc->outline_blend_mode;
|
|
|
|
|
|
|
|
|
|
/*Apply some optimization if there is no other mask*/
|
|
|
|
|
if(simple_mode) {
|
|
|
|
|
/*Draw the upper corner area*/
|
|
|
|
|
int32_t upper_corner_end = area_outer.y1 - disp_area->y1 + corner_size;
|
|
|
|
|
|
|
|
|
|
fill_area.x1 = area_outer.x1;
|
|
|
|
|
fill_area.x2 = area_outer.x2;
|
|
|
|
|
fill_area.y1 = disp_area->y1 + draw_area.y1;
|
|
|
|
|
fill_area.y2 = fill_area.y1;
|
|
|
|
|
for(h = draw_area.y1; h <= upper_corner_end; h++) {
|
|
|
|
|
_lv_memset_ff(mask_buf, draw_area_w);
|
|
|
|
|
mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w);
|
|
|
|
|
|
|
|
|
|
lv_area_t fill_area2;
|
|
|
|
|
fill_area2.y1 = fill_area.y1;
|
|
|
|
|
fill_area2.y2 = fill_area.y2;
|
|
|
|
|
|
|
|
|
|
fill_area2.x1 = area_outer.x1;
|
|
|
|
|
fill_area2.x2 = area_outer.x1 + rout - 1;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, mask_buf, mask_res, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
/*Draw the top horizontal line*/
|
|
|
|
|
if(fill_area2.y2 < area_outer.y1 + dsc->outline_width) {
|
|
|
|
|
fill_area2.x1 = area_outer.x1 + rout;
|
|
|
|
|
fill_area2.x2 = area_outer.x2 - rout;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fill_area2.x1 = area_outer.x2 - rout + 1;
|
|
|
|
|
fill_area2.x2 = area_outer.x2;
|
|
|
|
|
|
|
|
|
|
int32_t mask_ofs = (area_outer.x2 - rout + 1) - (vdb->area.x1 + draw_area.x1);
|
|
|
|
|
if(mask_ofs < 0) mask_ofs = 0;
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, mask_buf + mask_ofs, mask_res, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
fill_area.y1++;
|
|
|
|
|
fill_area.y2++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*Draw the lower corner area */
|
|
|
|
|
int32_t lower_corner_end = area_outer.y2 - disp_area->y1 - corner_size;
|
|
|
|
|
if(lower_corner_end <= upper_corner_end) lower_corner_end = upper_corner_end + 1;
|
|
|
|
|
fill_area.y1 = disp_area->y1 + lower_corner_end;
|
|
|
|
|
fill_area.y2 = fill_area.y1;
|
|
|
|
|
for(h = lower_corner_end; h <= draw_area.y2; h++) {
|
|
|
|
|
_lv_memset_ff(mask_buf, draw_area_w);
|
|
|
|
|
mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w);
|
|
|
|
|
|
|
|
|
|
lv_area_t fill_area2;
|
|
|
|
|
fill_area2.x1 = area_outer.x1;
|
|
|
|
|
fill_area2.x2 = area_outer.x1 + rout - 1;
|
|
|
|
|
fill_area2.y1 = fill_area.y1;
|
|
|
|
|
fill_area2.y2 = fill_area.y2;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, mask_buf, mask_res, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
/*Draw the bottom horizontal line*/
|
|
|
|
|
if(fill_area2.y2 > area_outer.y2 - dsc->outline_width) {
|
|
|
|
|
fill_area2.x1 = area_outer.x1 + rout;
|
|
|
|
|
fill_area2.x2 = area_outer.x2 - rout;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode);
|
|
|
|
|
}
|
|
|
|
|
fill_area2.x1 = area_outer.x2 - rout + 1;
|
|
|
|
|
fill_area2.x2 = area_outer.x2;
|
|
|
|
|
|
|
|
|
|
int32_t mask_ofs = (area_outer.x2 - rout + 1) - (vdb->area.x1 + draw_area.x1);
|
|
|
|
|
if(mask_ofs < 0) mask_ofs = 0;
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, mask_buf + mask_ofs, mask_res, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fill_area.y1++;
|
|
|
|
|
fill_area.y2++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*Draw the left vertical part*/
|
|
|
|
|
fill_area.y1 = area_outer.y1 + corner_size + 1;
|
|
|
|
|
fill_area.y2 = area_outer.y2 - corner_size - 1;
|
|
|
|
|
|
|
|
|
|
fill_area.x1 = area_outer.x1;
|
|
|
|
|
fill_area.x2 = area_outer.x1 + dsc->outline_width - 1;
|
|
|
|
|
_lv_blend_fill(clip, &fill_area, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
/*Draw the right vertical border*/
|
|
|
|
|
fill_area.x1 = area_outer.x2 - dsc->outline_width + 1;
|
|
|
|
|
fill_area.x2 = area_outer.x2;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode);
|
|
|
|
|
}
|
|
|
|
|
/*Process line by line if there is other mask too*/
|
|
|
|
|
else {
|
|
|
|
|
fill_area.x1 = area_outer.x1;
|
|
|
|
|
fill_area.x2 = area_outer.x2;
|
|
|
|
|
fill_area.y1 = disp_area->y1 + draw_area.y1;
|
|
|
|
|
fill_area.y2 = fill_area.y1;
|
|
|
|
|
|
|
|
|
|
for(h = draw_area.y1; h <= draw_area.y2; h++) {
|
|
|
|
|
_lv_memset_ff(mask_buf, draw_area_w);
|
|
|
|
|
mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w);
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area, color, mask_buf, mask_res, opa, blend_mode);
|
|
|
|
|
fill_area.y1++;
|
|
|
|
|
fill_area.y2++;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lv_draw_mask_remove_id(mask_rin_id);
|
|
|
|
|
lv_draw_mask_remove_id(mask_rout_id);
|
|
|
|
|
_lv_mem_buf_release(mask_buf);
|
|
|
|
|
draw_full_border(&area_inner, &area_outer, clip, dsc->radius, dsc->outline_color, dsc->outline_opa, dsc->outline_blend_mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void draw_pattern(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc)
|
|
|
|
|
@@ -1559,3 +1295,177 @@ static void draw_value(const lv_area_t * coords, const lv_area_t * clip, lv_draw
|
|
|
|
|
|
|
|
|
|
lv_draw_label(&value_area, clip, &label_dsc, dsc->value_str, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void draw_full_border(const lv_area_t * area_inner, const lv_area_t * area_outer, const lv_area_t * clip, lv_coord_t radius, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode)
|
|
|
|
|
{
|
|
|
|
|
uint8_t other_mask_cnt = lv_draw_mask_get_cnt();
|
|
|
|
|
bool simple_mode = true;
|
|
|
|
|
if(other_mask_cnt) simple_mode = false;
|
|
|
|
|
|
|
|
|
|
int32_t inner_w = lv_area_get_width(area_inner);
|
|
|
|
|
int32_t inner_h = lv_area_get_height(area_inner);
|
|
|
|
|
lv_coord_t border_width = area_outer->x2 - area_inner->x2;
|
|
|
|
|
int32_t rin = radius;
|
|
|
|
|
|
|
|
|
|
int32_t short_side = LV_MATH_MIN(inner_w, inner_h);
|
|
|
|
|
if(rin > short_side >> 1) rin = short_side >> 1;
|
|
|
|
|
|
|
|
|
|
/*Get the outer area*/
|
|
|
|
|
int32_t rout = rin + border_width;
|
|
|
|
|
|
|
|
|
|
int32_t coords_out_w = lv_area_get_width(area_outer);
|
|
|
|
|
int32_t coords_out_h = lv_area_get_height(area_outer);
|
|
|
|
|
short_side = LV_MATH_MIN(coords_out_w, coords_out_h);
|
|
|
|
|
if(rout > short_side >> 1) rout = short_side >> 1;
|
|
|
|
|
|
|
|
|
|
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
|
|
|
|
lv_disp_buf_t * vdb = lv_disp_get_buf(disp);
|
|
|
|
|
|
|
|
|
|
/* Get clipped fill area which is the real draw area.
|
|
|
|
|
* It is always the same or inside `fill_area` */
|
|
|
|
|
lv_area_t draw_area;
|
|
|
|
|
bool is_common;
|
|
|
|
|
is_common = _lv_area_intersect(&draw_area, area_outer, clip);
|
|
|
|
|
if(is_common == false) return;
|
|
|
|
|
|
|
|
|
|
const lv_area_t * disp_area = &vdb->area;
|
|
|
|
|
|
|
|
|
|
/* Now `draw_area` has absolute coordinates.
|
|
|
|
|
* Make it relative to `disp_area` to simplify draw to `disp_buf`*/
|
|
|
|
|
draw_area.x1 -= disp_area->x1;
|
|
|
|
|
draw_area.y1 -= disp_area->y1;
|
|
|
|
|
draw_area.x2 -= disp_area->x1;
|
|
|
|
|
draw_area.y2 -= disp_area->y1;
|
|
|
|
|
|
|
|
|
|
int32_t draw_area_w = lv_area_get_width(&draw_area);
|
|
|
|
|
|
|
|
|
|
/*Create inner the mask*/
|
|
|
|
|
lv_draw_mask_radius_param_t mask_rin_param;
|
|
|
|
|
lv_draw_mask_radius_init(&mask_rin_param, area_inner, rin, true);
|
|
|
|
|
int16_t mask_rin_id = lv_draw_mask_add(&mask_rin_param, NULL);
|
|
|
|
|
|
|
|
|
|
lv_draw_mask_radius_param_t mask_rout_param;
|
|
|
|
|
lv_draw_mask_radius_init(&mask_rout_param, area_outer, rout, false);
|
|
|
|
|
int16_t mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL);
|
|
|
|
|
|
|
|
|
|
lv_opa_t * mask_buf = _lv_mem_buf_get(draw_area_w);
|
|
|
|
|
|
|
|
|
|
int32_t corner_size = LV_MATH_MAX(rout, border_width - 1);
|
|
|
|
|
|
|
|
|
|
int32_t h;
|
|
|
|
|
lv_draw_mask_res_t mask_res;
|
|
|
|
|
lv_area_t fill_area;
|
|
|
|
|
|
|
|
|
|
/*Apply some optimization if there is no other mask*/
|
|
|
|
|
if(simple_mode) {
|
|
|
|
|
/*Draw the upper corner area*/
|
|
|
|
|
int32_t upper_corner_end = area_outer->y1 - disp_area->y1 + corner_size;
|
|
|
|
|
|
|
|
|
|
fill_area.x1 = area_outer->x1;
|
|
|
|
|
fill_area.x2 = area_outer->x2;
|
|
|
|
|
fill_area.y1 = disp_area->y1 + draw_area.y1;
|
|
|
|
|
fill_area.y2 = fill_area.y1;
|
|
|
|
|
for(h = draw_area.y1; h <= upper_corner_end; h++) {
|
|
|
|
|
_lv_memset_ff(mask_buf, draw_area_w);
|
|
|
|
|
mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w);
|
|
|
|
|
|
|
|
|
|
lv_area_t fill_area2;
|
|
|
|
|
fill_area2.y1 = fill_area.y1;
|
|
|
|
|
fill_area2.y2 = fill_area.y2;
|
|
|
|
|
|
|
|
|
|
fill_area2.x1 = area_outer->x1;
|
|
|
|
|
fill_area2.x2 = area_outer->x1 + rout - 1;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, mask_buf, mask_res, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
/*Draw the top horizontal line*/
|
|
|
|
|
if(fill_area2.y2 < area_outer->y1 + border_width) {
|
|
|
|
|
fill_area2.x1 = area_outer->x1 + rout;
|
|
|
|
|
fill_area2.x2 = area_outer->x2 - rout;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fill_area2.x1 = area_outer->x2 - rout + 1;
|
|
|
|
|
fill_area2.x2 = area_outer->x2;
|
|
|
|
|
|
|
|
|
|
int32_t mask_ofs = (area_outer->x2 - rout + 1) - (vdb->area.x1 + draw_area.x1);
|
|
|
|
|
if(mask_ofs < 0) mask_ofs = 0;
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, mask_buf + mask_ofs, mask_res, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
fill_area.y1++;
|
|
|
|
|
fill_area.y2++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*Draw the lower corner area */
|
|
|
|
|
int32_t lower_corner_end = area_outer->y2 - disp_area->y1 - corner_size;
|
|
|
|
|
if(lower_corner_end <= upper_corner_end) lower_corner_end = upper_corner_end + 1;
|
|
|
|
|
fill_area.y1 = disp_area->y1 + lower_corner_end;
|
|
|
|
|
fill_area.y2 = fill_area.y1;
|
|
|
|
|
for(h = lower_corner_end; h <= draw_area.y2; h++) {
|
|
|
|
|
_lv_memset_ff(mask_buf, draw_area_w);
|
|
|
|
|
mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w);
|
|
|
|
|
|
|
|
|
|
lv_area_t fill_area2;
|
|
|
|
|
fill_area2.x1 = area_outer->x1;
|
|
|
|
|
fill_area2.x2 = area_outer->x1 + rout - 1;
|
|
|
|
|
fill_area2.y1 = fill_area.y1;
|
|
|
|
|
fill_area2.y2 = fill_area.y2;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, mask_buf, mask_res, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
/*Draw the bottom horizontal line*/
|
|
|
|
|
if(fill_area2.y2 > area_outer->y2 - border_width) {
|
|
|
|
|
fill_area2.x1 = area_outer->x1 + rout;
|
|
|
|
|
fill_area2.x2 = area_outer->x2 - rout;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode);
|
|
|
|
|
}
|
|
|
|
|
fill_area2.x1 = area_outer->x2 - rout + 1;
|
|
|
|
|
fill_area2.x2 = area_outer->x2;
|
|
|
|
|
|
|
|
|
|
int32_t mask_ofs = (area_outer->x2 - rout + 1) - (vdb->area.x1 + draw_area.x1);
|
|
|
|
|
if(mask_ofs < 0) mask_ofs = 0;
|
|
|
|
|
_lv_blend_fill(clip, &fill_area2, color, mask_buf + mask_ofs, mask_res, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fill_area.y1++;
|
|
|
|
|
fill_area.y2++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*Draw the left vertical part*/
|
|
|
|
|
fill_area.y1 = area_outer->y1 + corner_size + 1;
|
|
|
|
|
fill_area.y2 = area_outer->y2 - corner_size - 1;
|
|
|
|
|
|
|
|
|
|
fill_area.x1 = area_outer->x1;
|
|
|
|
|
fill_area.x2 = area_outer->x1 + border_width - 1;
|
|
|
|
|
_lv_blend_fill(clip, &fill_area, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode);
|
|
|
|
|
|
|
|
|
|
/*Draw the right vertical border*/
|
|
|
|
|
fill_area.x1 = area_outer->x2 - border_width + 1;
|
|
|
|
|
fill_area.x2 = area_outer->x2;
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode);
|
|
|
|
|
}
|
|
|
|
|
/*Process line by line if there is other mask too*/
|
|
|
|
|
else {
|
|
|
|
|
fill_area.x1 = area_outer->x1;
|
|
|
|
|
fill_area.x2 = area_outer->x2;
|
|
|
|
|
fill_area.y1 = disp_area->y1 + draw_area.y1;
|
|
|
|
|
fill_area.y2 = fill_area.y1;
|
|
|
|
|
|
|
|
|
|
for(h = draw_area.y1; h <= draw_area.y2; h++) {
|
|
|
|
|
_lv_memset_ff(mask_buf, draw_area_w);
|
|
|
|
|
mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w);
|
|
|
|
|
|
|
|
|
|
_lv_blend_fill(clip, &fill_area, color, mask_buf, mask_res, opa, blend_mode);
|
|
|
|
|
fill_area.y1++;
|
|
|
|
|
fill_area.y2++;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lv_draw_mask_remove_id(mask_rin_id);
|
|
|
|
|
lv_draw_mask_remove_id(mask_rout_id);
|
|
|
|
|
_lv_mem_buf_release(mask_buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|