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

shadow drawing optimized

This commit is contained in:
Gabor Kiss-Vamosi 2018-02-16 12:55:05 +01:00
parent 2237ebd46e
commit c56f5421f0
3 changed files with 139 additions and 195 deletions

View File

@ -29,6 +29,8 @@
#define LABEL_RECOLOR_PAR_LENGTH 6 #define LABEL_RECOLOR_PAR_LENGTH 6
#define SHADOW_OPA_EXTRA_PRECISION 8 /*Calculate with 2^x bigger shadow opacity values to avoid rounding errors*/
#define SHADOW_BOTTOM_AA_EXTRA_RADIUS 4 /*Add extra radius with LV_SHADOW_BOTTOM to cover anti-aliased corners*/
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
@ -48,7 +50,7 @@ static void lv_draw_rect_main_corner(const lv_area_t * coords, const lv_area_t *
static void lv_draw_rect_border_straight(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style); static void lv_draw_rect_border_straight(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style);
static void lv_draw_rect_border_corner(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style); static void lv_draw_rect_border_corner(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style);
#if USE_LV_SHADOW && LV_VDB_SIZE #if USE_LV_SHADOW && LV_VDB_SIZE
static void lv_draw_rect_shadow(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style); static void lv_draw_cont_shadow(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style);
static void lv_draw_cont_shadow_full(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style); static void lv_draw_cont_shadow_full(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style);
static void lv_draw_cont_shadow_bottom(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style); static void lv_draw_cont_shadow_bottom(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style);
static void lv_draw_cont_shadow_full_straight(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, const lv_opa_t * map); static void lv_draw_cont_shadow_full_straight(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, const lv_opa_t * map);
@ -110,7 +112,7 @@ void lv_draw_rect(const lv_area_t * coords, const lv_area_t * mask, const lv_sty
#if USE_LV_SHADOW && LV_VDB_SIZE #if USE_LV_SHADOW && LV_VDB_SIZE
if(style->body.shadow.width != 0) { if(style->body.shadow.width != 0) {
lv_draw_rect_shadow(coords, mask, style); lv_draw_cont_shadow(coords, mask, style);
} }
#endif #endif
if(style->body.empty == 0){ if(style->body.empty == 0){
@ -784,7 +786,6 @@ void lv_draw_line(const lv_point_t * point1, const lv_point_t * point2, const lv
*/ */
static void lv_draw_rect_main_mid(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style) static void lv_draw_rect_main_mid(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style)
{ {
uint16_t radius = style->body.radius; uint16_t radius = style->body.radius;
lv_color_t mcolor = style->body.main_color; lv_color_t mcolor = style->body.main_color;
@ -807,12 +808,16 @@ static void lv_draw_rect_main_mid(const lv_area_t * coords, const lv_area_t * ma
work_area.y1 = coords->y1 + radius; work_area.y1 = coords->y1 + radius;
work_area.y2 = coords->y2 - radius; work_area.y2 = coords->y2 - radius;
#if LV_ANTIALIAS
if(style->body.radius != 0) { if(style->body.radius != 0) {
work_area.y1 += LV_ANTIALIAS * 2; #if LV_ANTIALIAS
work_area.y2 -= LV_ANTIALIAS * 2; work_area.y1 += 2;
} work_area.y2 -= 2;
#else
work_area.y1 += 1;
work_area.y2 -= 1;
#endif #endif
}
fill_fp(&work_area, mask, mcolor, opa); fill_fp(&work_area, mask, mcolor, opa);
} else { } else {
lv_coord_t row; lv_coord_t row;
@ -820,12 +825,15 @@ static void lv_draw_rect_main_mid(const lv_area_t * coords, const lv_area_t * ma
lv_coord_t row_end = coords->y2 - radius; lv_coord_t row_end = coords->y2 - radius;
lv_color_t act_color; lv_color_t act_color;
#if LV_ANTIALIAS
if(style->body.radius != 0) { if(style->body.radius != 0) {
row_start += LV_ANTIALIAS * 2; #if LV_ANTIALIAS
row_end -= LV_ANTIALIAS * 2; row_start += 2;
} row_end -= 2;
#else
row_start += 1;
row_end -= 1;
#endif #endif
}
if(row_start < 0) row_start = 0; if(row_start < 0) row_start = 0;
for(row = row_start; row <= row_end; row ++) for(row = row_start; row <= row_end; row ++)
@ -924,8 +932,6 @@ static void lv_draw_rect_main_corner(const lv_area_t * coords, const lv_area_t *
lv_coord_t seg_size = out_y_seg_end - out_y_seg_start; lv_coord_t seg_size = out_y_seg_end - out_y_seg_start;
lv_point_t aa_p; lv_point_t aa_p;
printf("x: %d, y:%d\n", out_x_last, out_y_seg_start);
aa_p.x = out_x_last; aa_p.x = out_x_last;
aa_p.y = out_y_seg_start; aa_p.y = out_y_seg_start;
@ -1117,7 +1123,6 @@ static void lv_draw_rect_main_corner(const lv_area_t * coords, const lv_area_t *
/*In some cases the last pixel is not drawn*/ /*In some cases the last pixel is not drawn*/
if(LV_MATH_ABS(aa_p.x - aa_p.y) == seg_size) { if(LV_MATH_ABS(aa_p.x - aa_p.y) == seg_size) {
printf("body out miss\n");
aa_p.x = out_x_last; aa_p.x = out_x_last;
aa_p.y = out_x_last; aa_p.y = out_x_last;
@ -1673,7 +1678,7 @@ static void lv_draw_rect_border_corner(const lv_area_t * coords, const lv_area_t
* @param rect pointer to rectangle object * @param rect pointer to rectangle object
* @param mask pointer to a mask area (from the design functions) * @param mask pointer to a mask area (from the design functions)
*/ */
static void lv_draw_rect_shadow(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style) static void lv_draw_cont_shadow(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style)
{ {
/* If mask is in the middle of cords do not draw shadow*/ /* If mask is in the middle of cords do not draw shadow*/
lv_coord_t radius = style->body.radius; lv_coord_t radius = style->body.radius;
@ -1711,7 +1716,12 @@ static void lv_draw_cont_shadow_full(const lv_area_t * coords, const lv_area_t *
lv_coord_t height = lv_area_get_height(coords); lv_coord_t height = lv_area_get_height(coords);
radius = lv_draw_cont_radius_corr(radius, width, height); radius = lv_draw_cont_radius_corr(radius, width, height);
lv_coord_t curve_x[radius + swidth]; /*Stores the 'x' coordinates of a quarter circle.*/
if(radius != 0) radius -= LV_ANTIALIAS;
swidth += LV_ANTIALIAS;
lv_coord_t curve_x[radius + swidth + 1]; /*Stores the 'x' coordinates of a quarter circle.*/
memset(curve_x, 0, sizeof(curve_x)); memset(curve_x, 0, sizeof(curve_x));
lv_point_t circ; lv_point_t circ;
lv_coord_t circ_tmp; lv_coord_t circ_tmp;
@ -1723,12 +1733,12 @@ static void lv_draw_cont_shadow_full(const lv_area_t * coords, const lv_area_t *
} }
int16_t line; int16_t line;
int16_t filter_size = 2 * swidth + 1; int16_t filter_width = 2 * swidth + 1;
uint16_t line_1d_blur[filter_size]; uint32_t line_1d_blur[filter_width];
/*1D Blur horizontally*/ /*1D Blur horizontally*/
for(line = 0; line < filter_size; line++) { for(line = 0; line < filter_width; line++) {
line_1d_blur[line] = (uint32_t)((uint32_t)(filter_size - line) * style->body.opa * 2) / filter_size; line_1d_blur[line] = (uint32_t)((uint32_t)(filter_width - line) * (style->body.opa * 2) << SHADOW_OPA_EXTRA_PRECISION) / (filter_width * filter_width);
} }
uint16_t col; uint16_t col;
@ -1742,62 +1752,65 @@ static void lv_draw_cont_shadow_full(const lv_area_t * coords, const lv_area_t *
lv_point_t ofs_rt; lv_point_t ofs_rt;
lv_point_t ofs_lb; lv_point_t ofs_lb;
lv_point_t ofs_lt; lv_point_t ofs_lt;
ofs_rb.x = coords->x2 - radius; ofs_rb.x = coords->x2 - radius - LV_ANTIALIAS;
ofs_rb.y = coords->y2 - radius; ofs_rb.y = coords->y2 - radius - LV_ANTIALIAS;
ofs_rt.x = coords->x2 - radius; ofs_rt.x = coords->x2 - radius - LV_ANTIALIAS;
ofs_rt.y = coords->y1 + radius; ofs_rt.y = coords->y1 + radius + LV_ANTIALIAS;
ofs_lb.x = coords->x1 + radius; ofs_lb.x = coords->x1 + radius + LV_ANTIALIAS;
ofs_lb.y = coords->y2 - radius; ofs_lb.y = coords->y2 - radius - LV_ANTIALIAS;
ofs_lt.x = coords->x1 + radius; ofs_lt.x = coords->x1 + radius + LV_ANTIALIAS;
ofs_lt.y = coords->y1 + radius; ofs_lt.y = coords->y1 + radius + LV_ANTIALIAS;
bool line_ready;
for(line = 0; line <= radius + swidth; line++) { /*Check all rows and make the 1D blur to 2D*/ for(line = 1; line <= radius + swidth; line++) { /*Check all rows and make the 1D blur to 2D*/
for(col = 0; col < radius + swidth; col++) { /*Check all pixels in a 1D blur line (from the origo to last shadow pixel (radius + swidth))*/ line_ready = false;
for(col = 1; col < radius + swidth + 1; col++) { /*Check all pixels in a 1D blur line (from the origo to last shadow pixel (radius + swidth))*/
/*Sum the opacities from the lines above and below this 'row'*/ /*Sum the opacities from the lines above and below this 'row'*/
int16_t line_rel; int16_t line_rel;
int16_t col_rel;
uint32_t px_opa_sum = 0; uint32_t px_opa_sum = 0;
for(line_rel = -swidth; line_rel <= swidth; line_rel ++) { for(line_rel = -swidth; line_rel <= swidth; line_rel ++) {
int16_t x_shift; /*Get the relative x position of the 'line_rel' to 'line'*/
int16_t col_rel;
if(line + line_rel < 0) { /*Below the radius, here is the blur of the edge */ if(line + line_rel < 0) { /*Below the radius, here is the blur of the edge */
x_shift = curve_x[line] + col; col_rel = radius - curve_x[line] - col;
} else if(line + line_rel > radius) { /*Above the radius, here won't be more 1D blur*/
if(x_shift - radius <= -swidth) px_opa_sum += style->body.opa * 2; /*Pointing inside, where no blur*/
else if(x_shift - radius >= swidth) px_opa_sum += 0; /*Already no blurred pixels here*/
else px_opa_sum += line_1d_blur[x_shift - radius + swidth]; /*On the 1D blur*/
}
else if(line + line_rel > radius) { /*Above the radius, here won't be more 1D blur*/
break; break;
} else { /*Blur from the curve*/ } else { /*Blur from the curve*/
x_shift = curve_x[line_rel] - curve_x[line_rel] + col; col_rel = curve_x[line + line_rel] - curve_x[line] - col;
if(x_shift <= -swidth) px_opa_sum += style->body.opa * 2; /*Inside the not blurred area*/
else if (x_shift >= swidth) px_opa_sum += 0; /*Outside of the burred area*/
else px_opa_sum += line_1d_blur[x_shift + swidth]; /*In the blur (+ swidth to align to the center)*/
} }
/*Add the value of the 1D blur on 'col_rel' position*/
if(col_rel < -swidth) { /*Outside of the burred area. */
if(line_rel == -swidth) line_ready = true; /*If no data even on the very first line then it wont't be anything else in this line*/
break; /*Break anyway because only smaller 'col_rel' values will come */
}
else if (col_rel > swidth) px_opa_sum += line_1d_blur[0]; /*Inside the not blurred area*/
else px_opa_sum += line_1d_blur[swidth - col_rel]; /*On the 1D blur (+ swidth to align to the center)*/
} }
line_2d_blur[col] = px_opa_sum / (radius + swidth); line_2d_blur[col] = px_opa_sum >> SHADOW_OPA_EXTRA_PRECISION;
if(line_ready) break;
} }
/*Flush the line*/ /*Flush the line*/
point_rt.x = curve_x[line] + ofs_rt.x; point_rt.x = curve_x[line] + ofs_rt.x + 1;
point_rt.y = ofs_rt.y - line; point_rt.y = ofs_rt.y - line;
point_rb.x = curve_x[line] + ofs_rb.x; point_rb.x = curve_x[line] + ofs_rb.x + 1;
point_rb.y = ofs_rb.y + line; point_rb.y = ofs_rb.y + line;
point_lt.x = ofs_lt.x - curve_x[line]; point_lt.x = ofs_lt.x - curve_x[line] - 1;
point_lt.y = ofs_lt.y - line; point_lt.y = ofs_lt.y - line;
point_lb.x = ofs_lb.x - curve_x[line]; point_lb.x = ofs_lb.x - curve_x[line] - 1;
point_lb.y = ofs_lb.y + line; point_lb.y = ofs_lb.y + line;
uint16_t d; uint16_t d;
for(d = 0; d < col; d++) { for(d = 1; d <= col; d++) {
if(point_rt.x != point_lt.x) { if(point_rt.x != point_lt.x) {
px_fp(point_lt.x,point_lt.y , mask, style->body.shadow.color, line_2d_blur[d]); px_fp(point_lt.x,point_lt.y , mask, style->body.shadow.color, line_2d_blur[d]);
@ -1820,91 +1833,11 @@ static void lv_draw_cont_shadow_full(const lv_area_t * coords, const lv_area_t *
point_rt.x++; point_rt.x++;
point_lt.x--; point_lt.x--;
} }
// for(p = 0; p < radius + swidth; p++) { /*Check all pixels in a row (from the origo to last shadow pixel (radius + swidth))*/
// int16_t v; /* Put the first line to the edges too.
// uint32_t opa_tmp = 0; * It is not correct because blur should be done below the corner too
// int16_t row_v; * but is is simple, fast and gives a good enough result*/
// bool swidth_out = false; if(line == 1) lv_draw_cont_shadow_full_straight(coords, mask, style, line_2d_blur);
//
// /* Count the sum of 1D blur 'lines'
// * v: relative 1D blur 'line' to this 'row' */
// for(v = -swidth; v <= swidth; v++) {
// row_v = row + v;
// if(row_v < 0) row_v = 0; /*Rows below the corner are the same as the last 1D blur (they are blurred from a straight edge)*/
//
// /*Rows above the bottom are empty so they won't modify the filter*/
// if(row_v > radius) {
// break;
// }
// else
// {
// int16_t p_tmp = p - (cruve_x[row_v] - cruve_x[row]); /*cruve_x[row_v]: 1D blur line start*/
// if(p_tmp < -swidth) { /*Cols before the filtered shadow (still not blurred)*/
// opa_tmp += style->body.opa * 2;
// }
// /*Cols after the filtered shadow (already no effect) */
// else if (p_tmp > swidth) {
// /* If on the current point the filter top point is already out of swidth then
// * the remaining part will not do not anything on this point*/
// if(v == -swidth) { /*Is the first point?*/
// swidth_out = true;
// }
// break;
// } else {
// opa_tmp += opa_h_result[p_tmp + swidth];
// }
// }
// }
// if(swidth_out == false) {
// opa_tmp = opa_tmp / (filter_size);
// opa_v_result[p] = opa_tmp > LV_OPA_COVER ? LV_OPA_COVER : opa_tmp;
// }
// else {
// break;
// }
// }
//
// point_rt.x = cruve_x[row] + ofs_rt.x;
// point_rt.y = ofs_rt.y - row;
//
// point_rb.x = cruve_x[row] + ofs_rb.x;
// point_rb.y = ofs_rb.y + row;
//
// point_lt.x = ofs_lt.x - cruve_x[row];
// point_lt.y = ofs_lt.y - row;
//
// point_lb.x = ofs_lb.x - cruve_x[row];
// point_lb.y = ofs_lb.y + row;
//
// uint16_t d;
// for(d = 0; d < p; d++) {
//
// if(point_rt.x != point_lt.x) {
// px_fp(point_lt.x,point_lt.y , mask, style->body.shadow.color, opa_v_result[d]);
// }
//
// if(point_rb.x != point_lb.x && point_lt.y != point_lb.y) {
// px_fp(point_lb.x,point_lb.y , mask, style->body.shadow.color, opa_v_result[d]);
// }
//
// if(point_lt.y != point_lb.y) {
// px_fp(point_rb.x,point_rb.y , mask, style->body.shadow.color, opa_v_result[d]);
// }
//
// px_fp(point_rt.x,point_rt.y , mask, style->body.shadow.color, opa_v_result[d]);
//
//
// point_rb.x++;
// point_lb.x--;
//
// point_rt.x++;
// point_lt.x--;
// }
//
// /*When the first row is known draw the straight pars with same opa. map*/
// if(row == 0) {
// lv_draw_cont_shadow_full_straight(coords, mask, style, opa_v_result);
// }
} }
} }
@ -1917,24 +1850,24 @@ static void lv_draw_cont_shadow_bottom(const lv_area_t * coords, const lv_area_t
lv_coord_t height = lv_area_get_height(coords); lv_coord_t height = lv_area_get_height(coords);
radius = lv_draw_cont_radius_corr(radius, width, height); radius = lv_draw_cont_radius_corr(radius, width, height);
radius += LV_ANTIALIAS * SHADOW_BOTTOM_AA_EXTRA_RADIUS;
swidth+= LV_ANTIALIAS;
lv_coord_t cruve_x[radius + swidth]; /*Stores the 'x' coordinates of a quarter circle.*/ lv_coord_t curve_x[radius + 1]; /*Stores the 'x' coordinates of a quarter circle.*/
memset(cruve_x, 0, sizeof(cruve_x));
lv_point_t circ; lv_point_t circ;
lv_coord_t circ_tmp; lv_coord_t circ_tmp;
lv_circ_init(&circ, &circ_tmp, radius); lv_circ_init(&circ, &circ_tmp, radius);
while(lv_circ_cont(&circ)) { while(lv_circ_cont(&circ)) {
cruve_x[LV_CIRC_OCT1_Y(circ)] = LV_CIRC_OCT1_X(circ); curve_x[LV_CIRC_OCT1_Y(circ)] = LV_CIRC_OCT1_X(circ);
cruve_x[LV_CIRC_OCT2_Y(circ)] = LV_CIRC_OCT2_X(circ); curve_x[LV_CIRC_OCT2_Y(circ)] = LV_CIRC_OCT2_X(circ);
lv_circ_next(&circ, &circ_tmp); lv_circ_next(&circ, &circ_tmp);
} }
int16_t row; int16_t row;
lv_opa_t line_1d_blur[swidth];
int16_t filter_size = 2 * swidth + 1; for(row = 0; row < swidth; row++) {
lv_opa_t opa_h_result[filter_size]; line_1d_blur[row] = (uint32_t)((uint32_t)(swidth - row) * style->body.opa) / (swidth);
for(row = 0; row < filter_size; row++) {
opa_h_result[row] = (uint32_t)((uint32_t)(filter_size - row) * style->body.opa) / (filter_size);
} }
lv_point_t point_l; lv_point_t point_l;
@ -1944,24 +1877,24 @@ static void lv_draw_cont_shadow_bottom(const lv_area_t * coords, const lv_area_t
lv_point_t ofs2; lv_point_t ofs2;
ofs1.x = coords->x1 + radius; ofs1.x = coords->x1 + radius;
ofs1.y = coords->y2 - radius; ofs1.y = coords->y2 - radius + 1 - LV_ANTIALIAS;
ofs2.x = coords->x2 - radius; ofs2.x = coords->x2 - radius;
ofs2.y = coords->y2 - radius; ofs2.y = coords->y2 - radius + 1 - LV_ANTIALIAS;
for(row = 0; row < radius; row++) { for(row = 0; row <= radius; row++) {
point_l.x = ofs1.x + radius - row - radius; point_l.x = ofs1.x + radius - row - radius;
point_l.y = ofs1.y + cruve_x[row]; point_l.y = ofs1.y + curve_x[row];
point_r.x = ofs2.x + row; point_r.x = ofs2.x + row;
point_r.y = ofs2.y + cruve_x[row]; point_r.y = ofs2.y + curve_x[row];
uint16_t d; uint16_t d;
for(d = swidth; d < filter_size; d++) { for(d = 0; d < swidth; d++) {
px_fp(point_l.x, point_l.y, mask, style->body.shadow.color, opa_h_result[d]); px_fp(point_l.x, point_l.y, mask, style->body.shadow.color, line_1d_blur[d]);
point_l.y ++; point_l.y ++;
px_fp(point_r.x, point_r.y, mask, style->body.shadow.color, opa_h_result[d]); px_fp(point_r.x, point_r.y, mask, style->body.shadow.color, line_1d_blur[d]);
point_r.y ++; point_r.y ++;
} }
@ -1973,8 +1906,8 @@ static void lv_draw_cont_shadow_bottom(const lv_area_t * coords, const lv_area_t
area_mid.y2 = area_mid.y1; area_mid.y2 = area_mid.y1;
uint16_t d; uint16_t d;
for(d = swidth; d < filter_size; d++) { for(d = 0; d < swidth; d++) {
fill_fp(&area_mid, mask, style->body.shadow.color, opa_h_result[d]); fill_fp(&area_mid, mask, style->body.shadow.color, line_1d_blur[d]);
area_mid.y1 ++; area_mid.y1 ++;
area_mid.y2 ++; area_mid.y2 ++;
} }
@ -1982,55 +1915,57 @@ static void lv_draw_cont_shadow_bottom(const lv_area_t * coords, const lv_area_t
static void lv_draw_cont_shadow_full_straight(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, const lv_opa_t * map) static void lv_draw_cont_shadow_full_straight(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, const lv_opa_t * map)
{ {
lv_coord_t radius = style->body.radius; lv_coord_t radius = style->body.radius;
lv_coord_t swidth = style->body.shadow.width; lv_coord_t swidth = style->body.shadow.width + LV_ANTIALIAS;
lv_coord_t width = lv_area_get_width(coords); lv_coord_t width = lv_area_get_width(coords);
lv_coord_t height = lv_area_get_height(coords); lv_coord_t height = lv_area_get_height(coords);
radius = lv_draw_cont_radius_corr(radius, width, height); radius = lv_draw_cont_radius_corr(radius, width, height);
if(radius == 0) radius += LV_ANTIALIAS;
lv_area_t sider_area; lv_area_t right_area;
sider_area.x1 = coords->x2; right_area.x1 = coords->x2 + 1 - LV_ANTIALIAS;
sider_area.y1 = coords->y1 + radius + 1; right_area.y1 = coords->y1 + radius;
sider_area.x2 = sider_area.x1; right_area.x2 = right_area.x1;
sider_area.y2 = coords->y2 - radius - 1; right_area.y2 = coords->y2 - radius;
lv_area_t sidel_area; lv_area_t left_area;
sidel_area.x1 = coords->x1; left_area.x1 = coords->x1 - 1 + LV_ANTIALIAS;
sidel_area.y1 = coords->y1 + radius + 1; left_area.y1 = coords->y1 + radius;
sidel_area.x2 = sidel_area.x1; left_area.x2 = left_area.x1;
sidel_area.y2 = coords->y2 - radius - 1; left_area.y2 = coords->y2 - radius;
lv_area_t sidet_area; lv_area_t top_area;
sidet_area.x1 = coords->x1 + radius + 1 + LV_ANTIALIAS; top_area.x1 = coords->x1 + radius;
sidet_area.y1 = coords->y1; top_area.y1 = coords->y1 - 1 + LV_ANTIALIAS;
sidet_area.x2 = coords->x2 - radius - 1; top_area.x2 = coords->x2 - radius;
sidet_area.y2 = sidet_area.y1; top_area.y2 = top_area.y1;
lv_area_t sideb_area; lv_area_t bottom_area;
sideb_area.x1 = coords->x1 + radius + 1; bottom_area.x1 = coords->x1 + radius;
sideb_area.y1 = coords->y2; bottom_area.y1 = coords->y2 + 1 - LV_ANTIALIAS;
sideb_area.x2 = coords->x2 - radius - 1; bottom_area.x2 = coords->x2 - radius;
sideb_area.y2 = sideb_area.y1; bottom_area.y2 = bottom_area.y1;
lv_opa_t opa_act;
int16_t d; int16_t d;
for(d = 0; d < swidth; d++) { for(d = 1; d <= swidth; d++) {
fill_fp(&sider_area, mask, style->body.shadow.color, map[d]); opa_act = map[d];
sider_area.x1++; fill_fp(&right_area, mask, style->body.shadow.color, opa_act);
sider_area.x2++; right_area.x1++;
right_area.x2++;
fill_fp(&sidel_area, mask, style->body.shadow.color, map[d]); fill_fp(&left_area, mask, style->body.shadow.color, opa_act);
sidel_area.x1--; left_area.x1--;
sidel_area.x2--; left_area.x2--;
fill_fp(&sidet_area, mask, style->body.shadow.color, map[d]); fill_fp(&top_area, mask, style->body.shadow.color, opa_act);
sidet_area.y1--; top_area.y1--;
sidet_area.y2--; top_area.y2--;
fill_fp(&sideb_area, mask, style->body.shadow.color, map[d]); fill_fp(&bottom_area, mask, style->body.shadow.color, opa_act);
sideb_area.y1++; bottom_area.y1++;
sideb_area.y2++; bottom_area.y2++;
} }
} }
@ -2111,7 +2046,6 @@ static lv_opa_t antialias_get_opa_circ(lv_coord_t seg, lv_coord_t px_id, lv_opa_
else { else {
uint8_t id = (uint32_t) ((uint32_t)px_id * (sizeof(opa_map) - 1)) / (seg - 1); uint8_t id = (uint32_t) ((uint32_t)px_id * (sizeof(opa_map) - 1)) / (seg - 1);
printf("id: %d, px/seg: %d/%d\n", id, px_id, seg);
return (uint32_t) ((uint32_t) opa_map[id] * opa) >> 8; return (uint32_t) ((uint32_t) opa_map[id] * opa) >> 8;
} }

View File

@ -38,8 +38,8 @@ typedef struct
* the result image converter utility*/ * the result image converter utility*/
typedef struct typedef struct
{ {
uint32_t w:12; /*Width of the image map*/ uint32_t w :12; /*Width of the image map*/
uint32_t h:12; /*Height of the image map*/ uint32_t h :12; /*Height of the image map*/
uint32_t chroma_key:1; /*1: The image contains transparent pixels with LV_COLOR_TRANSP color*/ uint32_t chroma_key:1; /*1: The image contains transparent pixels with LV_COLOR_TRANSP color*/
uint32_t alpha :1; /*Every pixel is extended with a 8 bit alpha channel*/ uint32_t alpha :1; /*Every pixel is extended with a 8 bit alpha channel*/
const uint8_t * pixel_map; const uint8_t * pixel_map;

View File

@ -384,7 +384,8 @@ void lv_vmap(const lv_area_t * cords_p, const lv_area_t * mask_p,
lv_opa_t opa_result = opa; lv_opa_t opa_result = opa;
lv_color_t * px_color = (lv_color_t *) &map_p[(uint32_t)col * px_size_byte]; lv_color_t * px_color = (lv_color_t *) &map_p[(uint32_t)col * px_size_byte];
if(chroma_key && px_color->full == chroma_key_color.full) continue; /*Handle chroma key*/ /*Handle chroma key*/
if(chroma_key && px_color->full == chroma_key_color.full) continue;
/*Calculate with the pixel level alpha*/ /*Calculate with the pixel level alpha*/
if(alpha_byte) { if(alpha_byte) {
@ -392,8 +393,17 @@ void lv_vmap(const lv_area_t * cords_p, const lv_area_t * mask_p,
opa_result = (uint32_t)((uint32_t)px_opa * opa_result) >> 8; opa_result = (uint32_t)((uint32_t)px_opa * opa_result) >> 8;
} }
if(opa_result == LV_OPA_COVER) vdb_buf_tmp[col].full = px_color->full; /*Re-color the pixel if required*/
else vdb_buf_tmp[col] = lv_color_mix(vdb_buf_tmp[col], *px_color, opa_result); if(recolor_opa != LV_OPA_TRANSP) {
lv_color_t recolored_px = lv_color_mix(recolor, *px_color, recolor_opa);
if(opa_result == LV_OPA_COVER) vdb_buf_tmp[col].full = recolored_px.full;
else vdb_buf_tmp[col] = lv_color_mix(vdb_buf_tmp[col], recolored_px, opa_result);
} else {
if(opa_result == LV_OPA_COVER) vdb_buf_tmp[col].full = px_color->full;
else vdb_buf_tmp[col] = lv_color_mix(vdb_buf_tmp[col], *px_color, opa_result);
}
} }