1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

lv_draw: new shadow drawing algorithm (filter based) introduced

This commit is contained in:
Kiss-Vamosi Gabor 2017-04-23 21:28:24 +02:00
parent 373bf2de84
commit 462244684e

View File

@ -48,6 +48,8 @@ static void lv_draw_cont_main_corner(const area_t * cords_p, const area_t * mask
static void lv_draw_cont_border_straight(const area_t * cords_p, const area_t * mask_p, const lv_style_t * style_p);
static void lv_draw_cont_border_corner(const area_t * cords_p, const area_t * mask_p, const lv_style_t * style);
static void lv_draw_cont_shadow(const area_t * cords_p, const area_t * mask_p, const lv_style_t * style);
static void lv_draw_cont_shadow_full_straight(const area_t * cords_p, const area_t * mask_p, const lv_style_t * style, const opa_t * map);
static uint16_t lv_draw_cont_radius_corr(uint16_t r, cord_t w, cord_t h);
#endif /*USE_LV_RECT != 0*/
@ -89,6 +91,10 @@ void lv_draw_rect(const area_t * cords_p, const area_t * mask_p, const lv_style_
{
if(area_get_height(cords_p) < 1 || area_get_width(cords_p) < 1) return;
if(style_p->swidth != 0) {
lv_draw_cont_shadow(cords_p, mask_p, style_p);
}
if(style_p->empty == 0){
lv_draw_cont_main_mid(cords_p, mask_p, style_p);
@ -105,9 +111,6 @@ void lv_draw_rect(const area_t * cords_p, const area_t * mask_p, const lv_style_
}
}
if(style_p->swidth != 0) {
lv_draw_cont_shadow(cords_p, mask_p, style_p);
}
}
#endif /*USE_LV_RECT != 0*/
@ -1039,6 +1042,7 @@ static void lv_draw_cont_border_corner(const area_t * cords_p, const area_t * ma
}
}
#define S_OLD 0
/**
* Draw a shadow
@ -1047,6 +1051,147 @@ static void lv_draw_cont_border_corner(const area_t * cords_p, const area_t * ma
*/
static void lv_draw_cont_shadow(const area_t * cords_p, const area_t * mask_p, const lv_style_t * style)
{
#if S_OLD == 0
cord_t radius = style->radius;
// if(mask_p->y1 > cords_p->y1 + radius && mask_p->y2 < cords_p->y2 - radius) return;
// if(mask_p->x1 > cords_p->x1 + radius && mask_p->x2 < cords_p->x2 - radius) return;
cord_t cruve_x[LV_VER_RES] = {CORD_MIN};
memset(cruve_x, 0, sizeof(cruve_x));
point_t circ;
cord_t circ_tmp;
circ_init(&circ, &circ_tmp, radius);
while(circ_cont(&circ)) {
cruve_x[CIRC_OCT1_Y(circ)] = CIRC_OCT1_X(circ);
cruve_x[CIRC_OCT2_Y(circ)] = CIRC_OCT2_X(circ);
circ_next(&circ, &circ_tmp);
}
int16_t row;
opa_t opa_h_result[LV_HOR_RES];
int16_t filter_size = 2 * style->swidth + 1;
for(row = 0; row < filter_size; row++) {
opa_h_result[row] = (uint32_t)((uint32_t)(filter_size - row) * OPA_COVER) / (filter_size);
}
for(; row < LV_HOR_RES; row++) {
opa_h_result[row] = OPA_COVER;
}
uint16_t p;
area_t sarea_rt;
area_t sarea_rb;
area_t sarea_lt;
area_t sarea_lb;
point_t ofs_rb;
point_t ofs_rt;
point_t ofs_lb;
point_t ofs_lt;
opa_t opa_v_result[LV_VER_RES];
ofs_rb.x = cords_p->x2 - radius;
ofs_rb.y = cords_p->y2 - radius;
ofs_rt.x = cords_p->x2 - radius;
ofs_rt.y = cords_p->y1 + radius;
ofs_lb.x = cords_p->x1 + radius;
ofs_lb.y = cords_p->y2 - radius;
ofs_lt.x = cords_p->x1 + radius;
ofs_lt.y = cords_p->y1 + radius;
for(row = 0; row < radius + style->swidth; row++) {
for(p = 0; p < radius + style->swidth; p++) {
int16_t v;
uint32_t opa_tmp = 0;
int16_t row_v;
bool swidth_out = false;
for(v = -style->swidth; v < style->swidth; v++) {
row_v = row + v;
if(row_v < 0) row_v = 0; /*Rows above the corner*/
/*Rows below 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]);
if(p_tmp < -style->swidth) { /*Cols before the filtered shadow (still not blurred)*/
opa_tmp += OPA_COVER;
}
/*Cols after the filtered shadow (already no effect) */
else if (p_tmp > style->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 == -style->swidth) { /*Is the first point?*/
swidth_out = true;
}
break;
} else {
opa_tmp += opa_h_result[p_tmp + style->swidth];
}
}
}
if(swidth_out == false) {
opa_tmp = opa_tmp / (filter_size);
opa_v_result[p] = opa_tmp;
}
else {
break;
}
}
sarea_rt.x1 = cruve_x[row] + ofs_rt.x;
sarea_rt.y1 = ofs_rt.y - row;
sarea_rt.x2 = sarea_rt.x1;
sarea_rt.y2 = sarea_rt.y1;
sarea_rb.x1 = cruve_x[row] + ofs_rb.x;
sarea_rb.y1 = ofs_rb.y + row;
sarea_rb.x2 = sarea_rt.x1;
sarea_rb.y2 = sarea_rb.y1;
sarea_lt.x1 = ofs_lt.x - cruve_x[row];
sarea_lt.y1 = ofs_lt.y - row;
sarea_lt.x2 = sarea_lt.x1;
sarea_lt.y2 = sarea_lt.y1;
sarea_lb.x1 = ofs_lb.x - cruve_x[row];
sarea_lb.y1 = ofs_lb.y + row;
sarea_lb.x2 = sarea_lb.x1;
sarea_lb.y2 = sarea_lb.y1;
uint16_t d;
for(d= 0; d < p; d++) {
fill_fp(&sarea_rb, mask_p, style->scolor, opa_v_result[d]);
sarea_rb.x1++;
sarea_rb.x2++;
fill_fp(&sarea_rt, mask_p, style->scolor, opa_v_result[d]);
sarea_rt.x1++;
sarea_rt.x2++;
fill_fp(&sarea_lb, mask_p, style->scolor, opa_v_result[d]);
sarea_lb.x1--;
sarea_lb.x2--;
fill_fp(&sarea_lt, mask_p, style->scolor, opa_v_result[d]);
sarea_lt.x1--;
sarea_lt.x2--;
}
/*When the first row is known draw the straight pars with same opa. map*/
if(row == 0) {
lv_draw_cont_shadow_full_straight(cords_p, mask_p, style, opa_v_result);
}
}
#else
cord_t swidth = style->swidth;
if(swidth == 0) return;
uint8_t res = LV_DOWNSCALE * 1;
@ -1074,9 +1219,14 @@ static void lv_draw_cont_shadow(const area_t * cords_p, const area_t * mask_p, c
shadow_area.y2 += swidth - 1;
cord_t i;
shadow_style.opa = style->opa / (swidth / res);
shadow_style.bopa = style->opa / (swidth / res);
static color_t x;
x.full = 0x1C224;
for(i = 1; i < swidth; i += res) {
x.full += 0xFCA34;
// shadow_style.bcolor.full = x.full;
lv_draw_cont_border_straight(&shadow_area, mask_p, &shadow_style);
lv_draw_cont_border_corner(&shadow_area, mask_p, &shadow_style);
shadow_style.radius -= res;
@ -1086,9 +1236,59 @@ static void lv_draw_cont_shadow(const area_t * cords_p, const area_t * mask_p, c
shadow_area.x2 -= res;
shadow_area.y2 -= res;
}
#endif
}
static void lv_draw_cont_shadow_full_straight(const area_t * cords_p, const area_t * mask_p, const lv_style_t * style, const opa_t * map)
{
cord_t radius = style->radius;
area_t sider_area;
sider_area.x1 = cords_p->x2;
sider_area.y1 = cords_p->y1 + radius + 1;
sider_area.x2 = sider_area.x1;
sider_area.y2 = cords_p->y2 - radius - 1;
area_t sidel_area;
sidel_area.x1 = cords_p->x1;
sidel_area.y1 = cords_p->y1 + radius + 1;
sidel_area.x2 = sidel_area.x1;
sidel_area.y2 = cords_p->y2 - radius - 1;
area_t sidet_area;
sidet_area.x1 = cords_p->x1 + radius + 1;
sidet_area.y1 = cords_p->y1;
sidet_area.x2 = cords_p->x2 - radius - 1;
sidet_area.y2 = sidet_area.y1;
area_t sideb_area;
sideb_area.x1 = cords_p->x1 + radius + 1;
sideb_area.y1 = cords_p->y2;
sideb_area.x2 = cords_p->x2 - radius - 1;
sideb_area.y2 = sideb_area.y1;
int16_t d;
for(d = 0; d < style->swidth; d++) {
fill_fp(&sider_area, mask_p, style->scolor, map[d]);
sider_area.x1++;
sider_area.x2++;
fill_fp(&sidel_area, mask_p, style->scolor, map[d]);
sidel_area.x1--;
sidel_area.x2--;
fill_fp(&sidet_area, mask_p, style->scolor, map[d]);
sidet_area.y1--;
sidet_area.y2--;
fill_fp(&sideb_area, mask_p, style->scolor, map[d]);
sideb_area.y1++;
sideb_area.y2++;
}
}
static uint16_t lv_draw_cont_radius_corr(uint16_t r, cord_t w, cord_t h)
{
if(r >= (w >> 1)){