mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-22 23:37:43 +08:00
perf(draw) reimplement rectangle drawing algorithms
No functionalty has changed only make them more readable and faster.
This commit is contained in:
+10
-15
@@ -140,16 +140,11 @@ LV_ATTRIBUTE_FAST_MEM void _lv_blend_fill(const lv_area_t * clip_area, const lv_
|
||||
/*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, clip_area, fill_area);
|
||||
if(!is_common) return;
|
||||
if(!_lv_area_intersect(&draw_area, clip_area, fill_area)) return;
|
||||
|
||||
/*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;
|
||||
*Make it relative to `disp_area` to simplify the drawing to `disp_buf`*/
|
||||
lv_area_move(&draw_area, -disp_area->x1, -disp_area->y1);
|
||||
|
||||
/*Round the values in the mask if anti-aliasing is disabled*/
|
||||
if(mask && disp->driver->antialiasing == 0 && mask) {
|
||||
@@ -390,13 +385,6 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
|
||||
}
|
||||
/*Masked*/
|
||||
else {
|
||||
/*Buffer the result color to avoid recalculating the same color*/
|
||||
lv_color_t last_dest_color;
|
||||
lv_color_t last_res_color;
|
||||
lv_opa_t last_mask = LV_OPA_TRANSP;
|
||||
last_dest_color.full = disp_buf_first[0].full;
|
||||
last_res_color.full = disp_buf_first[0].full;
|
||||
|
||||
int32_t x_end4 = draw_area_w - 4;
|
||||
|
||||
#if LV_COLOR_DEPTH == 16
|
||||
@@ -452,7 +440,14 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
|
||||
}
|
||||
/*Handle opa and mask values too*/
|
||||
else {
|
||||
/*Buffer the result color to avoid recalculating the same color*/
|
||||
lv_color_t last_dest_color;
|
||||
lv_color_t last_res_color;
|
||||
lv_opa_t last_mask = LV_OPA_TRANSP;
|
||||
last_dest_color.full = disp_buf_first[0].full;
|
||||
last_res_color.full = disp_buf_first[0].full;
|
||||
lv_opa_t opa_tmp = LV_OPA_TRANSP;
|
||||
|
||||
for(y = draw_area->y1; y <= draw_area->y2; y++) {
|
||||
const lv_opa_t * mask_tmp_x = mask;
|
||||
for(x = 0; x < draw_area_w; x++) {
|
||||
|
||||
@@ -211,6 +211,11 @@ LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void)
|
||||
return cnt;
|
||||
}
|
||||
|
||||
bool lv_draw_mask_is_any(void)
|
||||
{
|
||||
return LV_GC_ROOT(_lv_draw_mask_list[0]).param ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
*Initialize a line mask from two points.
|
||||
* @param param pointer to a `lv_draw_mask_param_t` to initialize
|
||||
@@ -1203,10 +1208,20 @@ static void circ_calc_aa4(_lv_draw_mask_radius_circle_dsc_t * c, lv_coord_t radi
|
||||
if(c->buf) lv_mem_free(c->buf);
|
||||
|
||||
c->buf = lv_mem_alloc(radius * 6 + 6); /*Use uint16_t for opa_start_on_y and x_start_on_y*/
|
||||
LV_ASSERT_MALLOC(c->buf);
|
||||
c->cir_opa = c->buf;
|
||||
c->opa_start_on_y = (uint16_t *) (c->buf + 2 * radius + 2);
|
||||
c->x_start_on_y = (uint16_t *) (c->buf + 4 * radius + 4);
|
||||
|
||||
/*Special case, handle manually*/
|
||||
if(radius == 1) {
|
||||
c->cir_opa[0] = 180;
|
||||
c->opa_start_on_y[0] = 0;
|
||||
c->opa_start_on_y[1] = 1;
|
||||
c->x_start_on_y[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
lv_coord_t * cir_x = lv_mem_buf_get((radius + 1) * 2 * 2 * sizeof(lv_coord_t));
|
||||
lv_coord_t * cir_y = &cir_x[(radius + 1) * 2];
|
||||
|
||||
|
||||
@@ -58,6 +58,11 @@ typedef _lv_draw_mask_saved_t _lv_draw_mask_saved_arr_t[_LV_MASK_MAX_NUM];
|
||||
static inline uint8_t lv_draw_mask_get_cnt(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool lv_draw_mask_is_any(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
@@ -269,6 +274,13 @@ void _lv_draw_mask_cleanup(void);
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void);
|
||||
|
||||
|
||||
/**
|
||||
* Check is there is any added draw mask
|
||||
* @return true: there is t least 1 draw mask; false: there are no draw masks
|
||||
*/
|
||||
bool lv_draw_mask_is_any(void);
|
||||
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
|
||||
+713
-833
File diff suppressed because it is too large
Load Diff
@@ -280,6 +280,44 @@ bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, lv_coo
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an area is fully out of an other
|
||||
* @param aout_p pointer to an area which could be in 'aholder_p'
|
||||
* @param aholder_p pointer to an area which could involve 'ain_p'
|
||||
* @param radius radius of `aholder_p` (e.g. for rounded rectangle)
|
||||
* @return true: `aout_p` is fully outside `aholder_p`
|
||||
*/
|
||||
bool _lv_area_is_out(const lv_area_t * aout_p, const lv_area_t * aholder_p, lv_coord_t radius)
|
||||
{
|
||||
if(aout_p->x2 < aholder_p->x1 || aout_p->y2 < aholder_p->y1 || aout_p->x1 > aholder_p->x2 ||
|
||||
aout_p->y1 > aholder_p->y2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(radius == 0) return true;
|
||||
|
||||
/*Check if the corner points are outside the radius or not*/
|
||||
lv_point_t p;
|
||||
|
||||
p.x = aout_p->x1;
|
||||
p.y = aout_p->y1;
|
||||
if(_lv_area_is_point_on(aholder_p, &p, radius)) return false;
|
||||
|
||||
p.x = aout_p->x2;
|
||||
p.y = aout_p->y1;
|
||||
if(_lv_area_is_point_on(aholder_p, &p, radius)) return false;
|
||||
|
||||
p.x = aout_p->x1;
|
||||
p.y = aout_p->y2;
|
||||
if(_lv_area_is_point_on(aholder_p, &p, radius)) return false;
|
||||
|
||||
p.x = aout_p->x2;
|
||||
p.y = aout_p->y2;
|
||||
if(_lv_area_is_point_on(aholder_p, &p, radius)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Align an area to an other
|
||||
* @param base an are where the other will be aligned
|
||||
|
||||
@@ -221,6 +221,16 @@ bool _lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p);
|
||||
*/
|
||||
bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, lv_coord_t radius);
|
||||
|
||||
|
||||
/**
|
||||
* Check if an area is fully out of an other
|
||||
* @param aout_p pointer to an area which could be in 'aholder_p'
|
||||
* @param aholder_p pointer to an area which could involve 'ain_p'
|
||||
* @param radius radius of `aholder_p` (e.g. for rounded rectangle)
|
||||
* @return true: `aout_p` is fully outside `aholder_p`
|
||||
*/
|
||||
bool _lv_area_is_out(const lv_area_t * aout_p, const lv_area_t * aholder_p, lv_coord_t radius);
|
||||
|
||||
/**
|
||||
* Align an area to an other
|
||||
* @param base an are where the other will be aligned
|
||||
|
||||
+9
-4
@@ -463,8 +463,8 @@ LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix(lv_color_t c1, lv_co
|
||||
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0
|
||||
/*Source: https://stackoverflow.com/a/50012418/1999969*/
|
||||
mix = ( mix + 4 ) >> 3;
|
||||
uint32_t bg = (c2.full | (c2.full << 16)) & 0x7E0F81F; /*0b00000111111000001111100000011111*/
|
||||
uint32_t fg = (c1.full | (c1.full << 16)) & 0x7E0F81F;
|
||||
uint32_t bg = (uint32_t)((uint32_t)c2.full | ((uint32_t)c2.full << 16)) & 0x7E0F81F; /*0b00000111111000001111100000011111*/
|
||||
uint32_t fg = (uint32_t)((uint32_t)c1.full | (uint32_t)(c1.full << 16)) & 0x7E0F81F;
|
||||
uint32_t result = ((((fg - bg) * mix) >> 5) + bg) & 0x7E0F81F;
|
||||
ret.full = (uint16_t)((result >> 16) | result);
|
||||
#elif LV_COLOR_DEPTH != 1
|
||||
@@ -512,8 +512,13 @@ LV_ATTRIBUTE_FAST_MEM static inline void lv_color_premult(lv_color_t c, uint8_t
|
||||
LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix_premult(uint16_t * premult_c1, lv_color_t c2, uint8_t mix)
|
||||
{
|
||||
lv_color_t ret;
|
||||
#if LV_COLOR_DEPTH != 1
|
||||
/*LV_COLOR_DEPTH == 8, 16 or 32*/
|
||||
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0
|
||||
/*For compatibility with lv_color_mix on 16 bit color depth*/
|
||||
LV_COLOR_SET_R(ret, (premult_c1[0] + LV_COLOR_GET_R(c2) * mix) >> 8);
|
||||
LV_COLOR_SET_G(ret, (premult_c1[1] + LV_COLOR_GET_G(c2) * mix) >> 8);
|
||||
LV_COLOR_SET_B(ret, (premult_c1[2] + LV_COLOR_GET_B(c2) * mix) >> 8);
|
||||
#elif LV_COLOR_DEPTH != 1
|
||||
/*LV_COLOR_DEPTH == 8 or 32*/
|
||||
LV_COLOR_SET_R(ret, LV_UDIV255(premult_c1[0] + LV_COLOR_GET_R(c2) * mix + LV_COLOR_MIX_ROUND_OFS));
|
||||
LV_COLOR_SET_G(ret, LV_UDIV255(premult_c1[1] + LV_COLOR_GET_G(c2) * mix + LV_COLOR_MIX_ROUND_OFS));
|
||||
LV_COLOR_SET_B(ret, LV_UDIV255(premult_c1[2] + LV_COLOR_GET_B(c2) * mix + LV_COLOR_MIX_ROUND_OFS));
|
||||
|
||||
@@ -731,6 +731,7 @@ static void lv_arc_draw(lv_event_t * e)
|
||||
part_draw_dsc.arc_dsc = &arc_dsc;
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc);
|
||||
|
||||
if(arc_dsc.width > part_draw_dsc.radius) arc_dsc.width = part_draw_dsc.radius;
|
||||
lv_draw_arc(center.x, center.y, part_draw_dsc.radius, arc->indic_angle_start +arc->rotation,
|
||||
arc->indic_angle_end + arc->rotation, clip_area,
|
||||
&arc_dsc);
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 18 KiB |
@@ -422,6 +422,7 @@ void test_dropdown_render_2(void)
|
||||
lv_dropdown_set_options(dd7, "1aaa\n2\n3");
|
||||
lv_dropdown_set_dir(dd7, LV_DIR_LEFT);
|
||||
lv_dropdown_set_symbol(dd7, LV_SYMBOL_LEFT);
|
||||
lv_obj_align(dd7, LV_ALIGN_BOTTOM_RIGHT, -20, -20);
|
||||
lv_dropdown_open(dd7);
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("dropdown_2.png");
|
||||
|
||||
Reference in New Issue
Block a user