perf(draw) reimplement circle drawing algorithms (#2374)
* perf(draw) reimplement circle drawing algorithms Imporve the speed of circle drawing Add circle draw caching Various other speed improvements * docs describe how to use masks * fix(draw) add missing GC root usage
This commit is contained in:
committed by
GitHub
parent
e23701e2c2
commit
637b706ddc
@@ -54,13 +54,13 @@ The difference between buffering modes regarding the drawing mechanism is the fo
|
|||||||
To use LVGL it's not required to know about the mechanisms described here, but you might find interesting to know how drawing works under hood.
|
To use LVGL it's not required to know about the mechanisms described here, but you might find interesting to know how drawing works under hood.
|
||||||
Knowing about masking comes in handy if you want to customize drawing.
|
Knowing about masking comes in handy if you want to customize drawing.
|
||||||
|
|
||||||
To learn masking let's learn the steps of drawing first.
|
To learn masking let's see the steps of drawing first.
|
||||||
LVGL performs the following steps to render any shape, image or text. It can be considered as a drawing pipeline.
|
LVGL performs the following steps to render any shape, image or text. It can be considered as a drawing pipeline.
|
||||||
|
|
||||||
1. **Prepare the draw descriptors** Create a draw descriptor from an object's styles (e.g. `lv_draw_rect_dsc_t`). This gives us the parameters for drawing, for example the colors, widths, opacity, fonts, radius, etc.
|
1. **Prepare the draw descriptors** Create a draw descriptor from an object's styles (e.g. `lv_draw_rect_dsc_t`). This gives us the parameters for drawing, for example the colors, widths, opacity, fonts, radius, etc.
|
||||||
2. **Call the draw function** Call the draw function with the draw descriptor and some other parameters (e.g. `lv_draw_rect()`). It renders the primitive shape to the current draw buffer.
|
2. **Call the draw function** Call the draw function with the draw descriptor and some other parameters (e.g. `lv_draw_rect()`). It will render the primitive shape to the current draw buffer.
|
||||||
3. **Create masks** If the shape is very simple and doesn't require masks go to #5. Else create the required masks (e.g. a rounded rectangle mask)
|
3. **Create masks** If the shape is very simple and doesn't require masks go to #5. Else create the required masks in the draw function. (e.g. a rounded rectangle mask)
|
||||||
4. **Calculate all the added mask**. It creates 0..255 values into a *mask buffer* with the "shape" of the created masks.
|
4. **Calculate all the added mask** It creates 0..255 values into a *mask buffer* with the "shape" of the created masks.
|
||||||
E.g. in case of a "line mask" according to the parameters of the mask, keep one side of the buffer as it is (255 by default) and set the rest to 0 to indicate that this side should be removed.
|
E.g. in case of a "line mask" according to the parameters of the mask, keep one side of the buffer as it is (255 by default) and set the rest to 0 to indicate that this side should be removed.
|
||||||
5. **Blend a color or image** During blending masks (make some pixels transparent or opaque), blending modes (additive, subtractive, etc) and opacity are handled.
|
5. **Blend a color or image** During blending masks (make some pixels transparent or opaque), blending modes (additive, subtractive, etc) and opacity are handled.
|
||||||
|
|
||||||
@@ -81,6 +81,25 @@ Masks are used the create almost every basic primitives:
|
|||||||
- **arc drawing** A circle border is drawn, but an arc mask is applied too.
|
- **arc drawing** A circle border is drawn, but an arc mask is applied too.
|
||||||
- **ARGB images** The alpha channel is separated into a mask and the image is drawn as a normal RGB image.
|
- **ARGB images** The alpha channel is separated into a mask and the image is drawn as a normal RGB image.
|
||||||
|
|
||||||
|
### Using masks
|
||||||
|
|
||||||
|
Every mask type has a related paramter to describe the mask's data. The following paramater types exist:
|
||||||
|
- `lv_draw_mask_line_param_t`
|
||||||
|
- `lv_draw_mask_radius_param_t`
|
||||||
|
- `lv_draw_mask_angle_param_t`
|
||||||
|
- `lv_draw_mask_fade_param_t`
|
||||||
|
- `lv_draw_mask_map_param_t`
|
||||||
|
|
||||||
|
1. Initialize a mask parameter with `lv_draw_mask_<type>_init`. See `lv_draw_mask.h` for the whole API.
|
||||||
|
2. Add the mask parameter to the draw engine with `int16_t mask_id = lv_draw_mask_add(¶m, ptr)`. `ptr` can be any pointer to identify the mask, (`NULL` if unused).
|
||||||
|
3. Call the draw functions
|
||||||
|
4. Remove the mask from the draw engine with `lv_draw_mask_remove_id(mask_id)` of `lv_draw_mask_remove_custom(ptr)`.
|
||||||
|
5. Free the parameter with `lv_draw_mask_free_param(¶m)`.
|
||||||
|
|
||||||
|
A parameter can be added and removed any number of times but it needs to be freed when not required anymore.
|
||||||
|
|
||||||
|
`lv_draw_mask_add` saves only the pointer of the mask so the parameter needs to be valid while in use.
|
||||||
|
|
||||||
## Hook drawing
|
## Hook drawing
|
||||||
Although widgets can be very well customized by styles there might be cases when something really custom is required.
|
Although widgets can be very well customized by styles there might be cases when something really custom is required.
|
||||||
To ensure a great level of flexibility LVGL sends a lot events during drawing with parameters that tell what LVGL is about to draw.
|
To ensure a great level of flexibility LVGL sends a lot events during drawing with parameters that tell what LVGL is about to draw.
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ static void draw_event_cb(lv_event_t * e)
|
|||||||
lv_draw_rect(&a, dsc->clip_area, &draw_rect_dsc);
|
lv_draw_rect(&a, dsc->clip_area, &draw_rect_dsc);
|
||||||
|
|
||||||
/*Remove the masks*/
|
/*Remove the masks*/
|
||||||
|
lv_draw_mask_free_param(&line_mask_param);
|
||||||
|
lv_draw_mask_free_param(&fade_mask_param);
|
||||||
lv_draw_mask_remove_id(line_mask_id);
|
lv_draw_mask_remove_id(line_mask_id);
|
||||||
lv_draw_mask_remove_id(fade_mask_id);
|
lv_draw_mask_remove_id(fade_mask_id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ static void mask_event_cb(lv_event_t * e)
|
|||||||
lv_draw_mask_fade_param_t * fade_mask_bottom = lv_draw_mask_remove_id(mask_bottom_id);
|
lv_draw_mask_fade_param_t * fade_mask_bottom = lv_draw_mask_remove_id(mask_bottom_id);
|
||||||
lv_mem_buf_release(fade_mask_top);
|
lv_mem_buf_release(fade_mask_top);
|
||||||
lv_mem_buf_release(fade_mask_bottom);
|
lv_mem_buf_release(fade_mask_bottom);
|
||||||
|
lv_draw_mask_free_param(&fade_mask_top);
|
||||||
|
lv_draw_mask_free_param(&fade_mask_bottom);
|
||||||
mask_top_id = -1;
|
mask_top_id = -1;
|
||||||
mask_bottom_id = -1;
|
mask_bottom_id = -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,6 +95,13 @@
|
|||||||
*LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius`
|
*LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius`
|
||||||
*Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/
|
*Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/
|
||||||
#define LV_SHADOW_CACHE_SIZE 0
|
#define LV_SHADOW_CACHE_SIZE 0
|
||||||
|
|
||||||
|
/* Set number of maximally cached circle data.
|
||||||
|
* The circumference of 1/4 circle are saved for anti-aliasing
|
||||||
|
* radius * 4 bytes are used per circle (the most often used radiuses are saved)
|
||||||
|
* 0: to disable caching */
|
||||||
|
#define LV_CIRCLE_CACHE_SIZE 4
|
||||||
|
|
||||||
#endif /*LV_DRAW_COMPLEX*/
|
#endif /*LV_DRAW_COMPLEX*/
|
||||||
|
|
||||||
/*Default image cache size. Image caching keeps the images opened.
|
/*Default image cache size. Image caching keeps the images opened.
|
||||||
|
|||||||
@@ -290,8 +290,9 @@ lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point)
|
|||||||
/*If the point is on this object check its children too*/
|
/*If the point is on this object check its children too*/
|
||||||
if(lv_obj_hit_test(obj, point)) {
|
if(lv_obj_hit_test(obj, point)) {
|
||||||
int32_t i;
|
int32_t i;
|
||||||
for(i = lv_obj_get_child_cnt(obj) - 1; i >= 0; i--) {
|
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
for(i = child_cnt - 1; i >= 0; i--) {
|
||||||
|
lv_obj_t * child = obj->spec_attr->children[i];
|
||||||
found_p = lv_indev_search_obj(child, point);
|
found_p = lv_indev_search_obj(child, point);
|
||||||
|
|
||||||
/*If a child was found then break*/
|
/*If a child was found then break*/
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coo
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||||
for(i = 0; i < child_cnt; i++) {
|
for(i = 0; i < child_cnt; i++) {
|
||||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
lv_obj_t * child = obj->spec_attr->children[i];
|
||||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||||
if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) {
|
if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) {
|
||||||
lv_coord_t x_child = 0;
|
lv_coord_t x_child = 0;
|
||||||
@@ -476,7 +476,7 @@ static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coo
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||||
for(i = 0; i < child_cnt; i++) {
|
for(i = 0; i < child_cnt; i++) {
|
||||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
lv_obj_t * child = obj->spec_attr->children[i];
|
||||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||||
if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) {
|
if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) {
|
||||||
lv_coord_t y_child = 0;
|
lv_coord_t y_child = 0;
|
||||||
|
|||||||
@@ -533,6 +533,7 @@ static void lv_obj_draw(lv_event_t * e)
|
|||||||
#if LV_DRAW_COMPLEX
|
#if LV_DRAW_COMPLEX
|
||||||
if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) {
|
if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) {
|
||||||
lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8);
|
lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8);
|
||||||
|
lv_draw_mask_free_param(param);
|
||||||
lv_mem_buf_release(param);
|
lv_mem_buf_release(param);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -781,7 +782,7 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||||
for(i = 0; i < child_cnt; i++) {
|
for(i = 0; i < child_cnt; i++) {
|
||||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
lv_obj_t * child = obj->spec_attr->children[i];
|
||||||
lv_obj_mark_layout_as_dirty(child);
|
lv_obj_mark_layout_as_dirty(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -754,7 +754,7 @@ void lv_obj_move_children_by(lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_dif
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||||
for(i = 0; i < child_cnt; i++) {
|
for(i = 0; i < child_cnt; i++) {
|
||||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
lv_obj_t * child = obj->spec_attr->children[i];
|
||||||
if(ignore_floating && lv_obj_has_flag(child, LV_OBJ_FLAG_FLOATING)) continue;
|
if(ignore_floating && lv_obj_has_flag(child, LV_OBJ_FLAG_FLOATING)) continue;
|
||||||
child->coords.x1 += x_diff;
|
child->coords.x1 += x_diff;
|
||||||
child->coords.y1 += y_diff;
|
child->coords.y1 += y_diff;
|
||||||
@@ -937,7 +937,7 @@ static void layout_update_core(lv_obj_t * obj)
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||||
for(i = 0; i < child_cnt; i++) {
|
for(i = 0; i < child_cnt; i++) {
|
||||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
lv_obj_t * child = obj->spec_attr->children[i];
|
||||||
layout_update_core(child);
|
layout_update_core(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -948,7 +948,7 @@ static void layout_update_core(lv_obj_t * obj)
|
|||||||
lv_obj_refr_size(obj);
|
lv_obj_refr_size(obj);
|
||||||
lv_obj_refr_pos(obj);
|
lv_obj_refr_pos(obj);
|
||||||
|
|
||||||
if(lv_obj_get_child_cnt(obj) > 0) {
|
if(child_cnt > 0) {
|
||||||
uint32_t layout_id = lv_obj_get_style_layout(obj, LV_PART_MAIN);
|
uint32_t layout_id = lv_obj_get_style_layout(obj, LV_PART_MAIN);
|
||||||
if(layout_id > 0 && layout_id <= layout_cnt) {
|
if(layout_id > 0 && layout_id <= layout_cnt) {
|
||||||
void * user_data = LV_GC_ROOT(_lv_layout_list)[layout_id -1].user_data;
|
void * user_data = LV_GC_ROOT(_lv_layout_list)[layout_id -1].user_data;
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj)
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||||
for(i = 0; i < child_cnt; i++) {
|
for(i = 0; i < child_cnt; i++) {
|
||||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
lv_obj_t * child = obj->spec_attr->children[i];
|
||||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||||
child_res = LV_MAX(child_res, child->coords.y2);
|
child_res = LV_MAX(child_res, child->coords.y2);
|
||||||
}
|
}
|
||||||
@@ -180,7 +180,7 @@ lv_coord_t lv_obj_get_scroll_left(lv_obj_t * obj)
|
|||||||
lv_coord_t x1 = LV_COORD_MAX;
|
lv_coord_t x1 = LV_COORD_MAX;
|
||||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||||
for(i = 0; i < child_cnt; i++) {
|
for(i = 0; i < child_cnt; i++) {
|
||||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
lv_obj_t * child = obj->spec_attr->children[i];
|
||||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||||
x1 = LV_MIN(x1, child->coords.x1);
|
x1 = LV_MIN(x1, child->coords.x1);
|
||||||
|
|
||||||
@@ -216,7 +216,7 @@ lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj)
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||||
for(i = 0; i < child_cnt; i++) {
|
for(i = 0; i < child_cnt; i++) {
|
||||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
lv_obj_t * child = obj->spec_attr->children[i];
|
||||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||||
child_res = LV_MAX(child_res, child->coords.x2);
|
child_res = LV_MAX(child_res, child->coords.x2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -623,7 +623,7 @@ static void report_style_change_core(void * style, lv_obj_t * obj)
|
|||||||
|
|
||||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||||
for(i = 0; i < child_cnt; i++) {
|
for(i = 0; i < child_cnt; i++) {
|
||||||
report_style_change_core(style, lv_obj_get_child(obj, i));
|
report_style_change_core(style, obj->spec_attr->children[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,7 +637,7 @@ static void refresh_children_style(lv_obj_t * obj)
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||||
for(i = 0; i < child_cnt; i++) {
|
for(i = 0; i < child_cnt; i++) {
|
||||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
lv_obj_t * child = obj->spec_attr->children[i];
|
||||||
lv_obj_invalidate(child);
|
lv_obj_invalidate(child);
|
||||||
lv_event_send(child, LV_EVENT_STYLE_CHANGED, NULL);
|
lv_event_send(child, LV_EVENT_STYLE_CHANGED, NULL);
|
||||||
lv_obj_invalidate(child);
|
lv_obj_invalidate(child);
|
||||||
|
|||||||
@@ -236,6 +236,10 @@ void _lv_disp_refr_timer(lv_timer_t * tmr)
|
|||||||
lv_mem_buf_free_all();
|
lv_mem_buf_free_all();
|
||||||
_lv_font_clean_up_fmt_txt();
|
_lv_font_clean_up_fmt_txt();
|
||||||
|
|
||||||
|
#if LV_DRAW_COMPLEX
|
||||||
|
_lv_draw_mask_cleanup();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if LV_USE_PERF_MONITOR && LV_USE_LABEL
|
#if LV_USE_PERF_MONITOR && LV_USE_LABEL
|
||||||
static lv_obj_t * perf_label = NULL;
|
static lv_obj_t * perf_label = NULL;
|
||||||
if(perf_label == NULL) {
|
if(perf_label == NULL) {
|
||||||
@@ -586,7 +590,7 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj)
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||||
for(i = 0; i < child_cnt; i++) {
|
for(i = 0; i < child_cnt; i++) {
|
||||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
lv_obj_t * child = obj->spec_attr->children[i];
|
||||||
found_p = lv_refr_get_top_obj(area_p, child);
|
found_p = lv_refr_get_top_obj(area_p, child);
|
||||||
|
|
||||||
/*If a children is ok then break*/
|
/*If a children is ok then break*/
|
||||||
@@ -634,7 +638,7 @@ static void lv_refr_obj_and_children(lv_obj_t * top_p, const lv_area_t * mask_p)
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t child_cnt = lv_obj_get_child_cnt(par);
|
uint32_t child_cnt = lv_obj_get_child_cnt(par);
|
||||||
for(i = 0; i < child_cnt; i++) {
|
for(i = 0; i < child_cnt; i++) {
|
||||||
lv_obj_t * child = lv_obj_get_child(par, i);
|
lv_obj_t * child = par->spec_attr->children[i];
|
||||||
if(!go) {
|
if(!go) {
|
||||||
if(child == border_p) go = true;
|
if(child == border_p) go = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -707,7 +711,7 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p)
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||||
for(i = 0; i < child_cnt; i++) {
|
for(i = 0; i < child_cnt; i++) {
|
||||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
lv_obj_t * child = obj->spec_attr->children[i];
|
||||||
lv_obj_get_coords(child, &child_area);
|
lv_obj_get_coords(child, &child_area);
|
||||||
ext_size = _lv_obj_get_ext_draw_size(child);
|
ext_size = _lv_obj_get_ext_draw_size(child);
|
||||||
child_area.x1 -= ext_size;
|
child_area.x1 -= ext_size;
|
||||||
|
|||||||
@@ -159,6 +159,11 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin
|
|||||||
else {
|
else {
|
||||||
lv_draw_rect(&area_out, clip_area, &cir_dsc);
|
lv_draw_rect(&area_out, clip_area, &cir_dsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lv_draw_mask_free_param(&mask_angle_param);
|
||||||
|
lv_draw_mask_free_param(&mask_out_param);
|
||||||
|
lv_draw_mask_free_param(&mask_in_param);
|
||||||
|
|
||||||
lv_draw_mask_remove_id(mask_angle_id);
|
lv_draw_mask_remove_id(mask_angle_id);
|
||||||
lv_draw_mask_remove_id(mask_out_id);
|
lv_draw_mask_remove_id(mask_out_id);
|
||||||
lv_draw_mask_remove_id(mask_in_id);
|
lv_draw_mask_remove_id(mask_in_id);
|
||||||
@@ -180,6 +185,7 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin
|
|||||||
|
|
||||||
lv_draw_rect(&area_out, &clip_area2, &cir_dsc);
|
lv_draw_rect(&area_out, &clip_area2, &cir_dsc);
|
||||||
lv_draw_mask_remove_id(mask_end_id);
|
lv_draw_mask_remove_id(mask_end_id);
|
||||||
|
lv_draw_mask_free_param(&mask_end_param);
|
||||||
}
|
}
|
||||||
|
|
||||||
get_rounded_area(end_angle, radius, width, &round_area);
|
get_rounded_area(end_angle, radius, width, &round_area);
|
||||||
@@ -193,6 +199,7 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin
|
|||||||
|
|
||||||
lv_draw_rect(&area_out, &clip_area2, &cir_dsc);
|
lv_draw_rect(&area_out, &clip_area2, &cir_dsc);
|
||||||
lv_draw_mask_remove_id(mask_end_id);
|
lv_draw_mask_remove_id(mask_end_id);
|
||||||
|
lv_draw_mask_free_param(&mask_end_param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -73,22 +73,21 @@ static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_co
|
|||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
**********************/
|
**********************/
|
||||||
|
#if LV_COLOR_SCREEN_TRANSP == 0
|
||||||
|
#define FILL_NORMAL_MASK_PX(color) \
|
||||||
|
if(*mask == LV_OPA_COVER) *disp_buf_first = color; \
|
||||||
|
else *disp_buf_first = lv_color_mix(color, *disp_buf_first, *mask); \
|
||||||
|
mask++; \
|
||||||
|
disp_buf_first++;
|
||||||
|
|
||||||
#define FILL_NORMAL_MASK_PX(out_x, color) \
|
#else
|
||||||
if(*mask_tmp_x) { \
|
#define FILL_NORMAL_MASK_PX(color) \
|
||||||
if(*mask_tmp_x == LV_OPA_COVER) disp_buf_first[out_x] = color; \
|
if(*mask == LV_OPA_COVER) *disp_buf_first = color; \
|
||||||
else disp_buf_first[out_x] = lv_color_mix(color, disp_buf_first[out_x], *mask_tmp_x); \
|
else if(disp->driver->screen_transp) lv_color_mix_with_alpha(*disp_buf_first, disp_buf_first->ch.alpha, color, *mask, disp_buf_first, &disp_buf_first->ch.alpha); \
|
||||||
} \
|
else *disp_buf_first = lv_color_mix(color, *disp_buf_first, *mask); \
|
||||||
mask_tmp_x++;
|
mask++; \
|
||||||
|
disp_buf_first++;
|
||||||
#define FILL_NORMAL_MASK_PX_SCR_TRANSP(out_x, color) \
|
#endif
|
||||||
if(*mask_tmp_x) { \
|
|
||||||
if(*mask_tmp_x == LV_OPA_COVER) disp_buf_first[out_x] = color; \
|
|
||||||
else if(disp->driver->screen_transp) lv_color_mix_with_alpha(disp_buf_first[out_x], disp_buf_first[out_x].ch.alpha, \
|
|
||||||
color, *mask_tmp_x, &disp_buf_first[out_x], &disp_buf_first[out_x].ch.alpha); \
|
|
||||||
else disp_buf_first[out_x] = lv_color_mix(color, disp_buf_first[out_x], *mask_tmp_x); \
|
|
||||||
} \
|
|
||||||
mask_tmp_x++;
|
|
||||||
|
|
||||||
#define MAP_NORMAL_MASK_PX(x) \
|
#define MAP_NORMAL_MASK_PX(x) \
|
||||||
if(*mask_tmp_x) { \
|
if(*mask_tmp_x) { \
|
||||||
@@ -326,7 +325,6 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
|
|||||||
if(lv_gpu_nxp_vglite_fill(disp_buf, disp_w, lv_area_get_height(disp_area), draw_area, color, opa) == LV_RES_OK) {
|
if(lv_gpu_nxp_vglite_fill(disp_buf, disp_w, lv_area_get_height(disp_area), draw_area, color, opa) == LV_RES_OK) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*Fall down to SW render in case of error*/
|
|
||||||
}
|
}
|
||||||
#elif LV_USE_GPU_STM32_DMA2D
|
#elif LV_USE_GPU_STM32_DMA2D
|
||||||
if(lv_area_get_size(draw_area) >= 240) {
|
if(lv_area_get_size(draw_area) >= 240) {
|
||||||
@@ -401,65 +399,55 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
|
|||||||
|
|
||||||
int32_t x_end4 = draw_area_w - 4;
|
int32_t x_end4 = draw_area_w - 4;
|
||||||
|
|
||||||
|
#if LV_COLOR_DEPTH == 16
|
||||||
|
uint32_t c32 = color.full + ((uint32_t)color.full << 16);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*Only the mask matters*/
|
/*Only the mask matters*/
|
||||||
if(opa > LV_OPA_MAX) {
|
if(opa > LV_OPA_MAX) {
|
||||||
for(y = 0; y < draw_area_h; y++) {
|
for(y = 0; y < draw_area_h; y++) {
|
||||||
const lv_opa_t * mask_tmp_x = mask;
|
for(x = 0; x < draw_area_w && ((lv_uintptr_t)(mask) & 0x3); x++) {
|
||||||
#if 0
|
FILL_NORMAL_MASK_PX(color)
|
||||||
for(x = 0; x < draw_area_w; x++) {
|
|
||||||
#if LV_COLOR_SCREEN_TRANSP
|
|
||||||
FILL_NORMAL_MASK_PX_SCR_TRANSP(x, color)
|
|
||||||
#else
|
|
||||||
FILL_NORMAL_MASK_PX(x, color)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
for(x = 0; x < draw_area_w && ((lv_uintptr_t)mask_tmp_x & 0x3); x++) {
|
|
||||||
#if LV_COLOR_SCREEN_TRANSP
|
|
||||||
FILL_NORMAL_MASK_PX_SCR_TRANSP(x, color)
|
|
||||||
#else
|
|
||||||
FILL_NORMAL_MASK_PX(x, color)
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t * mask32 = (uint32_t *)mask_tmp_x;
|
|
||||||
for(; x <= x_end4; x += 4) {
|
for(; x <= x_end4; x += 4) {
|
||||||
if(*mask32) {
|
uint32_t mask32 = *((uint32_t *)mask);
|
||||||
if((*mask32) == 0xFFFFFFFF) {
|
if(mask32 == 0xFFFFFFFF) {
|
||||||
disp_buf_first[x] = color;
|
#if LV_COLOR_DEPTH == 16
|
||||||
disp_buf_first[x + 1] = color;
|
if((lv_uintptr_t)disp_buf_first & 0x3) {
|
||||||
disp_buf_first[x + 2] = color;
|
*(disp_buf_first + 0) = color;
|
||||||
disp_buf_first[x + 3] = color;
|
uint32_t * d = (uint32_t * )(disp_buf_first + 1);
|
||||||
|
*d = c32;
|
||||||
|
*(disp_buf_first + 3) = color;
|
||||||
|
} else {
|
||||||
|
uint32_t * d = (uint32_t * )disp_buf_first;
|
||||||
|
*d = c32;
|
||||||
|
*(d + 1) = c32;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
mask_tmp_x = (const lv_opa_t *)mask32;
|
|
||||||
#if LV_COLOR_SCREEN_TRANSP
|
|
||||||
FILL_NORMAL_MASK_PX_SCR_TRANSP(x, color)
|
|
||||||
FILL_NORMAL_MASK_PX_SCR_TRANSP(x + 1, color)
|
|
||||||
FILL_NORMAL_MASK_PX_SCR_TRANSP(x + 2, color)
|
|
||||||
FILL_NORMAL_MASK_PX_SCR_TRANSP(x + 3, color)
|
|
||||||
#else
|
#else
|
||||||
FILL_NORMAL_MASK_PX(x, color)
|
disp_buf_first[0] = color;
|
||||||
FILL_NORMAL_MASK_PX(x + 1, color)
|
disp_buf_first[1] = color;
|
||||||
FILL_NORMAL_MASK_PX(x + 2, color)
|
disp_buf_first[2] = color;
|
||||||
FILL_NORMAL_MASK_PX(x + 3, color)
|
disp_buf_first[3] = color;
|
||||||
#endif
|
#endif
|
||||||
|
disp_buf_first+= 4;
|
||||||
|
mask += 4;
|
||||||
}
|
}
|
||||||
|
else if(mask32) {
|
||||||
|
FILL_NORMAL_MASK_PX(color)
|
||||||
|
FILL_NORMAL_MASK_PX(color)
|
||||||
|
FILL_NORMAL_MASK_PX(color)
|
||||||
|
FILL_NORMAL_MASK_PX(color)
|
||||||
|
} else {
|
||||||
|
mask += 4;
|
||||||
|
disp_buf_first += 4;
|
||||||
}
|
}
|
||||||
mask32++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mask_tmp_x = (const lv_opa_t *)mask32;
|
|
||||||
for(; x < draw_area_w ; x++) {
|
for(; x < draw_area_w ; x++) {
|
||||||
#if LV_COLOR_SCREEN_TRANSP
|
FILL_NORMAL_MASK_PX(color)
|
||||||
FILL_NORMAL_MASK_PX_SCR_TRANSP(x, color)
|
|
||||||
#else
|
|
||||||
FILL_NORMAL_MASK_PX(x, color)
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
disp_buf_first += (disp_w-draw_area_w);
|
||||||
disp_buf_first += disp_w;
|
|
||||||
mask += draw_area_w;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*Handle opa and mask values too*/
|
/*Handle opa and mask values too*/
|
||||||
@@ -701,8 +689,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col
|
|||||||
blit.src_stride = lv_area_get_width(map_area) * sizeof(lv_color_t);
|
blit.src_stride = lv_area_get_width(map_area) * sizeof(lv_color_t);
|
||||||
blit.src_area.x1 = (draw_area->x1 - (map_area->x1 - disp_area->x1));
|
blit.src_area.x1 = (draw_area->x1 - (map_area->x1 - disp_area->x1));
|
||||||
blit.src_area.y1 = (draw_area->y1 - (map_area->y1 - disp_area->y1));
|
blit.src_area.y1 = (draw_area->y1 - (map_area->y1 - disp_area->y1));
|
||||||
blit.src_area.x2 = blit.src_area.x1 + draw_area_w - 1;
|
blit.src_area.x2 = blit.src_area.x1 + draw_area_w;
|
||||||
blit.src_area.y2 = blit.src_area.y1 + draw_area_h - 1;
|
blit.src_area.y2 = blit.src_area.y1 + draw_area_h;
|
||||||
|
|
||||||
blit.dst = disp_buf;
|
blit.dst = disp_buf;
|
||||||
blit.dst_width = lv_area_get_width(disp_area);
|
blit.dst_width = lv_area_get_width(disp_area);
|
||||||
@@ -710,8 +698,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col
|
|||||||
blit.dst_stride = lv_area_get_width(disp_area) * sizeof(lv_color_t);
|
blit.dst_stride = lv_area_get_width(disp_area) * sizeof(lv_color_t);
|
||||||
blit.dst_area.x1 = draw_area->x1;
|
blit.dst_area.x1 = draw_area->x1;
|
||||||
blit.dst_area.y1 = draw_area->y1;
|
blit.dst_area.y1 = draw_area->y1;
|
||||||
blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w - 1;
|
blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w;
|
||||||
blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h - 1;
|
blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h;
|
||||||
|
|
||||||
blit.opa = opa;
|
blit.opa = opa;
|
||||||
|
|
||||||
@@ -751,8 +739,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col
|
|||||||
blit.src_stride = lv_area_get_width(map_area) * sizeof(lv_color_t);
|
blit.src_stride = lv_area_get_width(map_area) * sizeof(lv_color_t);
|
||||||
blit.src_area.x1 = (draw_area->x1 - (map_area->x1 - disp_area->x1));
|
blit.src_area.x1 = (draw_area->x1 - (map_area->x1 - disp_area->x1));
|
||||||
blit.src_area.y1 = (draw_area->y1 - (map_area->y1 - disp_area->y1));
|
blit.src_area.y1 = (draw_area->y1 - (map_area->y1 - disp_area->y1));
|
||||||
blit.src_area.x2 = blit.src_area.x1 + draw_area_w - 1;
|
blit.src_area.x2 = blit.src_area.x1 + draw_area_w;
|
||||||
blit.src_area.y2 = blit.src_area.y1 + draw_area_h - 1;
|
blit.src_area.y2 = blit.src_area.y1 + draw_area_h;
|
||||||
|
|
||||||
blit.dst = disp_buf;
|
blit.dst = disp_buf;
|
||||||
blit.dst_width = lv_area_get_width(disp_area);
|
blit.dst_width = lv_area_get_width(disp_area);
|
||||||
@@ -760,8 +748,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col
|
|||||||
blit.dst_stride = lv_area_get_width(disp_area) * sizeof(lv_color_t);
|
blit.dst_stride = lv_area_get_width(disp_area) * sizeof(lv_color_t);
|
||||||
blit.dst_area.x1 = draw_area->x1;
|
blit.dst_area.x1 = draw_area->x1;
|
||||||
blit.dst_area.y1 = draw_area->y1;
|
blit.dst_area.y1 = draw_area->y1;
|
||||||
blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w - 1;
|
blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w;
|
||||||
blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h - 1;
|
blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h;
|
||||||
|
|
||||||
blit.opa = opa;
|
blit.opa = opa;
|
||||||
|
|
||||||
@@ -933,14 +921,8 @@ static void map_blended(const lv_area_t * disp_area, lv_color_t * disp_buf, con
|
|||||||
|
|
||||||
for(y = draw_area->y1; y <= draw_area->y2; y++) {
|
for(y = draw_area->y1; y <= draw_area->y2; y++) {
|
||||||
for(x = draw_area->x1; x <= draw_area->x2; x++) {
|
for(x = draw_area->x1; x <= draw_area->x2; x++) {
|
||||||
#if LV_COLOR_DEPTH == 32
|
|
||||||
if(map_buf_tmp[x].full != 0xff000000) {
|
|
||||||
#else
|
|
||||||
if(map_buf_tmp[x].full != 0) {
|
|
||||||
#endif
|
|
||||||
disp_buf_tmp[x] = blend_fp(map_buf_tmp[x], disp_buf_tmp[x], opa);
|
disp_buf_tmp[x] = blend_fp(map_buf_tmp[x], disp_buf_tmp[x], opa);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
disp_buf_tmp += disp_w;
|
disp_buf_tmp += disp_w;
|
||||||
map_buf_tmp += map_w;
|
map_buf_tmp += map_w;
|
||||||
}
|
}
|
||||||
@@ -957,15 +939,8 @@ static void map_blended(const lv_area_t * disp_area, lv_color_t * disp_buf, con
|
|||||||
for(x = draw_area->x1; x <= draw_area->x2; x++) {
|
for(x = draw_area->x1; x <= draw_area->x2; x++) {
|
||||||
if(mask_tmp[x] == 0) continue;
|
if(mask_tmp[x] == 0) continue;
|
||||||
lv_opa_t opa_tmp = mask_tmp[x] >= LV_OPA_MAX ? opa : ((opa * mask_tmp[x]) >> 8);
|
lv_opa_t opa_tmp = mask_tmp[x] >= LV_OPA_MAX ? opa : ((opa * mask_tmp[x]) >> 8);
|
||||||
#if LV_COLOR_DEPTH == 32
|
|
||||||
if(map_buf_tmp[x].full != 0xff000000) {
|
|
||||||
#else
|
|
||||||
if(map_buf_tmp[x].full != 0) {
|
|
||||||
#endif
|
|
||||||
disp_buf_tmp[x] = blend_fp(map_buf_tmp[x], disp_buf_tmp[x], opa_tmp);
|
disp_buf_tmp[x] = blend_fp(map_buf_tmp[x], disp_buf_tmp[x], opa_tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
disp_buf_tmp += disp_w;
|
disp_buf_tmp += disp_w;
|
||||||
mask_tmp += draw_area_w;
|
mask_tmp += draw_area_w;
|
||||||
map_buf_tmp += map_w;
|
map_buf_tmp += map_w;
|
||||||
@@ -975,6 +950,9 @@ static void map_blended(const lv_area_t * disp_area, lv_color_t * disp_buf, con
|
|||||||
|
|
||||||
static inline lv_color_t color_blend_true_color_additive(lv_color_t fg, lv_color_t bg, lv_opa_t opa)
|
static inline lv_color_t color_blend_true_color_additive(lv_color_t fg, lv_color_t bg, lv_opa_t opa)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if(opa <= LV_OPA_MIN) return bg;
|
||||||
|
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
#if LV_COLOR_DEPTH == 1
|
#if LV_COLOR_DEPTH == 1
|
||||||
tmp = bg.full + fg.full;
|
tmp = bg.full + fg.full;
|
||||||
@@ -990,7 +968,6 @@ static inline lv_color_t color_blend_true_color_additive(lv_color_t fg, lv_color
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LV_COLOR_DEPTH == 8
|
#if LV_COLOR_DEPTH == 8
|
||||||
tmp = bg.ch.green + fg.ch.green;
|
|
||||||
fg.ch.green = LV_MIN(tmp, 7);
|
fg.ch.green = LV_MIN(tmp, 7);
|
||||||
#elif LV_COLOR_DEPTH == 16
|
#elif LV_COLOR_DEPTH == 16
|
||||||
#if LV_COLOR_16_SWAP == 0
|
#if LV_COLOR_16_SWAP == 0
|
||||||
@@ -1004,7 +981,6 @@ static inline lv_color_t color_blend_true_color_additive(lv_color_t fg, lv_color
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif LV_COLOR_DEPTH == 32
|
#elif LV_COLOR_DEPTH == 32
|
||||||
tmp = bg.ch.green + fg.ch.green;
|
|
||||||
fg.ch.green = LV_MIN(tmp, 255);
|
fg.ch.green = LV_MIN(tmp, 255);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -474,6 +474,10 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_skew(const lv_point_t * point1, cons
|
|||||||
|
|
||||||
lv_mem_buf_release(mask_buf);
|
lv_mem_buf_release(mask_buf);
|
||||||
|
|
||||||
|
lv_draw_mask_free_param(&mask_left_param);
|
||||||
|
lv_draw_mask_free_param(&mask_right_param);
|
||||||
|
if(mask_top_id != LV_MASK_ID_INV) lv_draw_mask_free_param(&mask_top_param);
|
||||||
|
if(mask_bottom_id != LV_MASK_ID_INV) lv_draw_mask_free_param(&mask_bottom_param);
|
||||||
lv_draw_mask_remove_id(mask_left_id);
|
lv_draw_mask_remove_id(mask_left_id);
|
||||||
lv_draw_mask_remove_id(mask_right_id);
|
lv_draw_mask_remove_id(mask_right_id);
|
||||||
lv_draw_mask_remove_id(mask_top_id);
|
lv_draw_mask_remove_id(mask_top_id);
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
/*********************
|
/*********************
|
||||||
* INCLUDES
|
* INCLUDES
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
|
|
||||||
#include "lv_draw_mask.h"
|
#include "lv_draw_mask.h"
|
||||||
#if LV_DRAW_COMPLEX
|
#if LV_DRAW_COMPLEX
|
||||||
#include "../misc/lv_math.h"
|
#include "../misc/lv_math.h"
|
||||||
@@ -18,6 +16,8 @@
|
|||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
*********************/
|
*********************/
|
||||||
|
#define CIRCLE_CACHE_LIFE_MAX 1000
|
||||||
|
#define CIRCLE_CACHE_AGING(life, r) life = LV_MIN(life + (r < 16 ? 1 : (r >> 4)), 1000)
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* TYPEDEFS
|
* TYPEDEFS
|
||||||
@@ -49,8 +49,12 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_
|
|||||||
lv_coord_t len,
|
lv_coord_t len,
|
||||||
lv_draw_mask_line_param_t * p);
|
lv_draw_mask_line_param_t * p);
|
||||||
|
|
||||||
|
static void circ_init(lv_point_t * c, lv_coord_t * tmp, lv_coord_t radius);
|
||||||
|
static bool circ_cont(lv_point_t * c);
|
||||||
|
static void circ_next(lv_point_t * c, lv_coord_t * tmp);
|
||||||
|
static void circ_calc_aa4(_lv_draw_mask_radius_circle_dsc_t * c, lv_coord_t radius);
|
||||||
|
static lv_opa_t * get_next_line(_lv_draw_mask_radius_circle_dsc_t * c, lv_coord_t y, lv_coord_t * len, lv_coord_t * x_start);
|
||||||
LV_ATTRIBUTE_FAST_MEM static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new);
|
LV_ATTRIBUTE_FAST_MEM static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new);
|
||||||
LV_ATTRIBUTE_FAST_MEM static inline void sqrt_approx(lv_sqrt_res_t * q, lv_sqrt_res_t * ref, uint32_t x);
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC VARIABLES
|
* STATIC VARIABLES
|
||||||
@@ -129,7 +133,7 @@ LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf,
|
|||||||
*/
|
*/
|
||||||
void * lv_draw_mask_remove_id(int16_t id)
|
void * lv_draw_mask_remove_id(int16_t id)
|
||||||
{
|
{
|
||||||
void * p = NULL;
|
_lv_draw_mask_common_dsc_t * p = NULL;
|
||||||
|
|
||||||
if(id != LV_MASK_ID_INV) {
|
if(id != LV_MASK_ID_INV) {
|
||||||
p = LV_GC_ROOT(_lv_draw_mask_list[id]).param;
|
p = LV_GC_ROOT(_lv_draw_mask_list[id]).param;
|
||||||
@@ -148,18 +152,51 @@ void * lv_draw_mask_remove_id(int16_t id)
|
|||||||
*/
|
*/
|
||||||
void * lv_draw_mask_remove_custom(void * custom_id)
|
void * lv_draw_mask_remove_custom(void * custom_id)
|
||||||
{
|
{
|
||||||
void * p = NULL;
|
_lv_draw_mask_common_dsc_t * 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(LV_GC_ROOT(_lv_draw_mask_list[i]).custom_id == custom_id) {
|
if(LV_GC_ROOT(_lv_draw_mask_list[i]).custom_id == custom_id) {
|
||||||
p = LV_GC_ROOT(_lv_draw_mask_list[i]).param;
|
p = LV_GC_ROOT(_lv_draw_mask_list[i]).param;
|
||||||
LV_GC_ROOT(_lv_draw_mask_list[i]).param = NULL;
|
lv_draw_mask_remove_id(i);
|
||||||
LV_GC_ROOT(_lv_draw_mask_list[i]).custom_id = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free the data from the parameter.
|
||||||
|
* It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom`
|
||||||
|
* Needs to be called only in special cases when the mask is not added by `lv_draw_mask_add`
|
||||||
|
* and not removed by `lv_draw_mask_remove_id` or `lv_draw_mask_remove_custom`
|
||||||
|
* @param p pointer to a mask parameter
|
||||||
|
*/
|
||||||
|
void lv_draw_mask_free_param(void * p)
|
||||||
|
{
|
||||||
|
_lv_draw_mask_common_dsc_t * pdsc = p;
|
||||||
|
if(pdsc->type == LV_DRAW_MASK_TYPE_RADIUS) {
|
||||||
|
lv_draw_mask_radius_param_t * radius_p = (lv_draw_mask_radius_param_t *) p;
|
||||||
|
if(radius_p->circle) {
|
||||||
|
if(radius_p->circle->life < 0) {
|
||||||
|
lv_mem_free(radius_p->circle->cir_opa);
|
||||||
|
lv_mem_free(radius_p->circle);
|
||||||
|
} else {
|
||||||
|
radius_p->circle->used_cnt--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _lv_draw_mask_cleanup(void)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
for(i = 0; i < LV_CIRCLE_CACHE_SIZE; i++) {
|
||||||
|
if(LV_GC_ROOT(_lv_circle_cache[i]).buf) {
|
||||||
|
lv_mem_free(LV_GC_ROOT(_lv_circle_cache[i]).buf);
|
||||||
|
}
|
||||||
|
lv_memset_00(&LV_GC_ROOT(_lv_circle_cache[i]), sizeof(LV_GC_ROOT(_lv_circle_cache[i])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count the currently added masks
|
* Count the currently added masks
|
||||||
* @return number of active masks
|
* @return number of active masks
|
||||||
@@ -373,6 +410,7 @@ void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area
|
|||||||
{
|
{
|
||||||
lv_coord_t w = lv_area_get_width(rect);
|
lv_coord_t w = lv_area_get_width(rect);
|
||||||
lv_coord_t h = lv_area_get_height(rect);
|
lv_coord_t h = lv_area_get_height(rect);
|
||||||
|
if(radius < 0) radius = 0;
|
||||||
int32_t short_side = LV_MIN(w, h);
|
int32_t short_side = LV_MIN(w, h);
|
||||||
if(radius > short_side >> 1) radius = short_side >> 1;
|
if(radius > short_side >> 1) radius = short_side >> 1;
|
||||||
|
|
||||||
@@ -381,9 +419,47 @@ void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area
|
|||||||
param->cfg.outer = inv ? 1 : 0;
|
param->cfg.outer = inv ? 1 : 0;
|
||||||
param->dsc.cb = (lv_draw_mask_xcb_t)lv_draw_mask_radius;
|
param->dsc.cb = (lv_draw_mask_xcb_t)lv_draw_mask_radius;
|
||||||
param->dsc.type = LV_DRAW_MASK_TYPE_RADIUS;
|
param->dsc.type = LV_DRAW_MASK_TYPE_RADIUS;
|
||||||
param->y_prev = INT32_MIN;
|
|
||||||
param->y_prev_x.f = 0;
|
if(radius == 0) {
|
||||||
param->y_prev_x.i = 0;
|
param->circle = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
/*Try to reuse a circle cache entry*/
|
||||||
|
for(i = 0; i < LV_CIRCLE_CACHE_SIZE; i++) {
|
||||||
|
if(LV_GC_ROOT(_lv_circle_cache[i]).radius == radius) {
|
||||||
|
LV_GC_ROOT(_lv_circle_cache[i]).used_cnt++;
|
||||||
|
CIRCLE_CACHE_AGING(LV_GC_ROOT(_lv_circle_cache[i]).life, radius);
|
||||||
|
param->circle = &LV_GC_ROOT(_lv_circle_cache[i]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*If not found find a free entry with lowest life*/
|
||||||
|
_lv_draw_mask_radius_circle_dsc_t * entry = NULL;
|
||||||
|
for(i = 0; i < LV_CIRCLE_CACHE_SIZE; i++) {
|
||||||
|
if(LV_GC_ROOT(_lv_circle_cache[i]).used_cnt == 0) {
|
||||||
|
if(!entry) entry = &LV_GC_ROOT(_lv_circle_cache[i]);
|
||||||
|
else if(LV_GC_ROOT(_lv_circle_cache[i]).life < entry->life) entry = &LV_GC_ROOT(_lv_circle_cache[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!entry) {
|
||||||
|
entry = lv_mem_alloc(sizeof(_lv_draw_mask_radius_circle_dsc_t));
|
||||||
|
LV_ASSERT_MALLOC(param->circle);
|
||||||
|
lv_memset_00(entry, sizeof(_lv_draw_mask_radius_circle_dsc_t));
|
||||||
|
entry->life = -1;
|
||||||
|
} else {
|
||||||
|
entry->used_cnt++;
|
||||||
|
entry->life = 0;
|
||||||
|
CIRCLE_CACHE_AGING(entry->life, radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
param->circle = entry;
|
||||||
|
|
||||||
|
circ_calc_aa4(param->circle, radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -881,6 +957,8 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * ma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x,
|
LV_ATTRIBUTE_FAST_MEM 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_coord_t abs_y, lv_coord_t len,
|
||||||
lv_draw_mask_radius_param_t * p)
|
lv_draw_mask_radius_param_t * p)
|
||||||
@@ -891,7 +969,7 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * m
|
|||||||
lv_area_copy(&rect, &p->cfg.rect);
|
lv_area_copy(&rect, &p->cfg.rect);
|
||||||
|
|
||||||
if(outer == false) {
|
if(outer == false) {
|
||||||
if(abs_y < rect.y1 || abs_y > rect.y2) {
|
if((abs_y < rect.y1 || abs_y > rect.y2)) {
|
||||||
return LV_DRAW_MASK_RES_TRANSP;
|
return LV_DRAW_MASK_RES_TRANSP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -932,6 +1010,13 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * m
|
|||||||
}
|
}
|
||||||
return LV_DRAW_MASK_RES_CHANGED;
|
return LV_DRAW_MASK_RES_CHANGED;
|
||||||
}
|
}
|
||||||
|
// printf("exec: x:%d.. %d, y:%d: r:%d, %s\n", abs_x, abs_x + len - 1, abs_y, p->cfg.radius, p->cfg.outer ? "inv" : "norm");
|
||||||
|
|
||||||
|
|
||||||
|
// if( abs_x == 276 && abs_x + len - 1 == 479 && abs_y == 63 && p->cfg.radius == 5 && p->cfg.outer == 1) {
|
||||||
|
// char x = 0;
|
||||||
|
// }
|
||||||
|
//exec: x:276.. 479, y:63: r:5, inv)
|
||||||
|
|
||||||
int32_t k = rect.x1 - abs_x; /*First relevant coordinate on the of the mask*/
|
int32_t k = rect.x1 - abs_x; /*First relevant coordinate on the of the mask*/
|
||||||
int32_t w = lv_area_get_width(&rect);
|
int32_t w = lv_area_get_width(&rect);
|
||||||
@@ -939,194 +1024,51 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * m
|
|||||||
abs_x -= rect.x1;
|
abs_x -= rect.x1;
|
||||||
abs_y -= rect.y1;
|
abs_y -= rect.y1;
|
||||||
|
|
||||||
uint32_t r2 = p->cfg.radius * p->cfg.radius;
|
lv_coord_t aa_len;
|
||||||
|
lv_coord_t x_start;
|
||||||
/*Handle corner areas*/
|
lv_coord_t cir_y;
|
||||||
if(abs_y < radius || abs_y > h - radius - 1) {
|
|
||||||
|
|
||||||
uint32_t sqrt_mask;
|
|
||||||
if(radius <= 32) sqrt_mask = 0x200;
|
|
||||||
if(radius <= 256) sqrt_mask = 0x800;
|
|
||||||
else sqrt_mask = 0x8000;
|
|
||||||
|
|
||||||
lv_sqrt_res_t x0;
|
|
||||||
lv_sqrt_res_t x1;
|
|
||||||
/*y = 0 should mean the top of the circle*/
|
|
||||||
int32_t y;
|
|
||||||
if(abs_y < radius) {
|
if(abs_y < radius) {
|
||||||
y = radius - abs_y;
|
cir_y = radius - abs_y - 1;
|
||||||
|
} else {
|
||||||
/*Get the x intersection points for `abs_y` and `abs_y-1`
|
cir_y = abs_y - (h - radius);
|
||||||
*Use the circle's equation x = sqrt(r^2 - y^2)
|
|
||||||
*Try to use the values from the previous run*/
|
|
||||||
if(y == p->y_prev) {
|
|
||||||
x0.f = p->y_prev_x.f;
|
|
||||||
x0.i = p->y_prev_x.i;
|
|
||||||
}
|
}
|
||||||
else {
|
lv_opa_t * aa_opa = get_next_line(p->circle, cir_y, &aa_len, &x_start);
|
||||||
lv_sqrt(r2 - (y * y), &x0, sqrt_mask);
|
lv_coord_t cir_x_right = k + w - radius + x_start;
|
||||||
}
|
lv_coord_t cir_x_left = k + radius - x_start - 1;
|
||||||
lv_sqrt(r2 - ((y - 1) * (y - 1)), &x1, sqrt_mask);
|
lv_coord_t i;
|
||||||
p->y_prev = y - 1;
|
|
||||||
p->y_prev_x.f = x1.f;
|
|
||||||
p->y_prev_x.i = x1.i;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
y = radius - (h - 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)
|
|
||||||
*Try to use the values from the previous run*/
|
|
||||||
if((y - 1) == p->y_prev) {
|
|
||||||
x1.f = p->y_prev_x.f;
|
|
||||||
x1.i = p->y_prev_x.i;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
lv_sqrt(r2 - ((y - 1) * (y - 1)), &x1, sqrt_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
lv_sqrt(r2 - (y * y), &x0, sqrt_mask);
|
|
||||||
p->y_prev = y;
|
|
||||||
p->y_prev_x.f = x0.f;
|
|
||||||
p->y_prev_x.i = x0.i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*If x1 is on the next round coordinate (e.g. x0: 3.5, x1:4.0)
|
|
||||||
*then treat x1 as x1: 3.99 to handle them as they were on the same pixel*/
|
|
||||||
if(x0.i == x1.i - 1 && x1.f == 0) {
|
|
||||||
x1.i--;
|
|
||||||
x1.f = 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*If the two x intersections are on the same x then just get average of the fractions*/
|
|
||||||
if(x0.i == x1.i) {
|
|
||||||
lv_opa_t m = (x0.f + x1.f) >> 1;
|
|
||||||
if(outer) m = 255 - m;
|
|
||||||
int32_t ofs = radius - x0.i - 1;
|
|
||||||
|
|
||||||
/*Left corner*/
|
|
||||||
int32_t kl = k + ofs;
|
|
||||||
|
|
||||||
if(kl >= 0 && kl < len) {
|
|
||||||
mask_buf[kl] = mask_mix(mask_buf[kl], m);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Right corner*/
|
|
||||||
int32_t kr = k + (w - ofs - 1);
|
|
||||||
if(kr >= 0 && kr < len) {
|
|
||||||
mask_buf[kr] = mask_mix(mask_buf[kr], m);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Clear the unused parts*/
|
|
||||||
if(outer == false) {
|
if(outer == false) {
|
||||||
kr++;
|
for(i = 0; i < aa_len; i++) {
|
||||||
if(kl > len) {
|
lv_opa_t opa = aa_opa[aa_len - i - 1];
|
||||||
return LV_DRAW_MASK_RES_TRANSP;
|
if(cir_x_right + i >= 0 && cir_x_right + i < len) {
|
||||||
|
mask_buf[cir_x_right + i] = mask_mix(opa, mask_buf[cir_x_right + i]);
|
||||||
}
|
}
|
||||||
if(kl >= 0) {
|
if(cir_x_left - i >= 0 && cir_x_left - i < len) {
|
||||||
lv_memset_00(&mask_buf[0], kl);
|
mask_buf[cir_x_left - i] = mask_mix(opa, mask_buf[cir_x_left - i]);
|
||||||
}
|
|
||||||
if(kr < 0) {
|
|
||||||
return LV_DRAW_MASK_RES_TRANSP;
|
|
||||||
}
|
|
||||||
if(kr <= len) {
|
|
||||||
lv_memset_00(&mask_buf[kr], len - kr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
kl++;
|
|
||||||
int32_t first = kl;
|
|
||||||
if(first < 0) first = 0;
|
|
||||||
|
|
||||||
int32_t len_tmp = kr - first;
|
|
||||||
if(len_tmp + first > len) len_tmp = len - first;
|
|
||||||
if(first < len && len_tmp >= 0) {
|
|
||||||
lv_memset_00(&mask_buf[first], len_tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*Multiple pixels are affected. Get y intersection of the pixels*/
|
|
||||||
else {
|
|
||||||
int32_t ofs = radius - (x0.i + 1);
|
|
||||||
int32_t kl = k + ofs;
|
|
||||||
int32_t kr = k + (w - ofs - 1);
|
|
||||||
|
|
||||||
if(outer) {
|
|
||||||
int32_t first = kl + 1;
|
|
||||||
if(first < 0) first = 0;
|
|
||||||
|
|
||||||
int32_t len_tmp = kr - first;
|
|
||||||
if(len_tmp + first > len) len_tmp = len - first;
|
|
||||||
if(first < len && len_tmp >= 0) {
|
|
||||||
lv_memset_00(&mask_buf[first], len_tmp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t i = x0.i + 1;
|
/*Clean the right side*/
|
||||||
lv_opa_t m;
|
cir_x_right = LV_CLAMP(0, cir_x_right + i, len);
|
||||||
lv_sqrt_res_t y_prev;
|
lv_memset_00(&mask_buf[cir_x_right], len - cir_x_right);
|
||||||
lv_sqrt_res_t y_next;
|
|
||||||
|
|
||||||
lv_sqrt(r2 - (x0.i * x0.i), &y_prev, sqrt_mask);
|
/*Clean the left side*/
|
||||||
|
cir_x_left = LV_CLAMP(0, cir_x_left - aa_len + 1, len);
|
||||||
if(y_prev.f == 0) {
|
lv_memset_00(&mask_buf[0], cir_x_left);
|
||||||
y_prev.i--;
|
} else {
|
||||||
y_prev.f = 0xFF;
|
for(i = 0; i < aa_len; i++) {
|
||||||
|
lv_opa_t opa = 255 - (aa_opa[aa_len - 1 - i]);
|
||||||
|
if(cir_x_right + i >= 0 && cir_x_right + i < len) {
|
||||||
|
mask_buf[cir_x_right + i] = mask_mix(opa, mask_buf[cir_x_right + i]);
|
||||||
}
|
}
|
||||||
|
if(cir_x_left - i >= 0 && cir_x_left - i < len) {
|
||||||
/*The first y intersection is special as it might be in the previous line*/
|
mask_buf[cir_x_left - i] = mask_mix(opa, mask_buf[cir_x_left - i]);
|
||||||
if(y_prev.i >= y) {
|
|
||||||
lv_sqrt(r2 - (i * i), &y_next, sqrt_mask);
|
|
||||||
m = 255 - (((255 - x0.f) * (255 - y_next.f)) >> 9);
|
|
||||||
|
|
||||||
if(outer) m = 255 - 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);
|
|
||||||
kl--;
|
|
||||||
kr++;
|
|
||||||
y_prev.f = y_next.f;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Set all points which are crossed by the circle*/
|
|
||||||
for(; i <= x1.i; i++) {
|
|
||||||
/*These values are very close to each other. It's enough to approximate sqrt
|
|
||||||
*The non-approximated version is lv_sqrt(r2 - (i * i), &y_next, sqrt_mask);*/
|
|
||||||
sqrt_approx(&y_next, &y_prev, r2 - (i * i));
|
|
||||||
|
|
||||||
m = (y_prev.f + y_next.f) >> 1;
|
|
||||||
if(outer) m = 255 - 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);
|
|
||||||
kl--;
|
|
||||||
kr++;
|
|
||||||
y_prev.f = y_next.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*If the last pixel was left in its middle therefore
|
|
||||||
* the circle still has parts on the next one*/
|
|
||||||
if(y_prev.f) {
|
|
||||||
m = (y_prev.f * x1.f) >> 9;
|
|
||||||
if(outer) m = 255 - 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);
|
|
||||||
kl--;
|
|
||||||
kr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(outer == 0) {
|
|
||||||
kl++;
|
|
||||||
if(kl > len) {
|
|
||||||
return LV_DRAW_MASK_RES_TRANSP;
|
|
||||||
}
|
|
||||||
if(kl >= 0) lv_memset_00(&mask_buf[0], kl);
|
|
||||||
|
|
||||||
if(kr < 0) {
|
|
||||||
return LV_DRAW_MASK_RES_TRANSP;
|
|
||||||
}
|
|
||||||
if(kr < len) lv_memset_00(&mask_buf[kr], len - kr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lv_coord_t clr_start = LV_CLAMP(0, cir_x_left + 1, len);
|
||||||
|
lv_coord_t clr_len = LV_CLAMP(0, cir_x_right - clr_start, len - clr_start);
|
||||||
|
lv_memset_00(&mask_buf[clr_start], clr_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
return LV_DRAW_MASK_RES_CHANGED;
|
return LV_DRAW_MASK_RES_CHANGED;
|
||||||
@@ -1212,6 +1154,191 @@ LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_map(lv_opa_t * mask
|
|||||||
return LV_DRAW_MASK_RES_CHANGED;
|
return LV_DRAW_MASK_RES_CHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the circle drawing
|
||||||
|
* @param c pointer to a point. The coordinates will be calculated here
|
||||||
|
* @param tmp point to a variable. It will store temporary data
|
||||||
|
* @param radius radius of the circle
|
||||||
|
*/
|
||||||
|
static void circ_init(lv_point_t * c, lv_coord_t * tmp, lv_coord_t radius)
|
||||||
|
{
|
||||||
|
c->x = radius;
|
||||||
|
c->y = 0;
|
||||||
|
*tmp = 1 - radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the circle drawing is ready or not
|
||||||
|
* @param c same as in circ_init
|
||||||
|
* @return true if the circle is not ready yet
|
||||||
|
*/
|
||||||
|
static bool circ_cont(lv_point_t * c)
|
||||||
|
{
|
||||||
|
return c->y <= c->x ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next point from the circle
|
||||||
|
* @param c same as in circ_init. The next point stored here.
|
||||||
|
* @param tmp same as in circ_init.
|
||||||
|
*/
|
||||||
|
static void circ_next(lv_point_t * c, lv_coord_t * tmp)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(*tmp <= 0) {
|
||||||
|
(*tmp) += 2 * c->y + 3; /*Change in decision criterion for y -> y+1*/
|
||||||
|
} else {
|
||||||
|
(*tmp) += 2 * (c->y - c->x) + 5; /*Change for y -> y+1, x -> x-1*/
|
||||||
|
c->x--;
|
||||||
|
}
|
||||||
|
c->y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void circ_calc_aa4(_lv_draw_mask_radius_circle_dsc_t * c, lv_coord_t radius)
|
||||||
|
{
|
||||||
|
if(radius == 0) return;
|
||||||
|
c->radius = radius;
|
||||||
|
|
||||||
|
/*Allocate buffers*/
|
||||||
|
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*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
uint32_t y_8th_cnt = 0;
|
||||||
|
lv_point_t cp;
|
||||||
|
lv_coord_t tmp;
|
||||||
|
circ_init(&cp, &tmp, radius * 4); /*Upscale by 4*/
|
||||||
|
int32_t i;
|
||||||
|
|
||||||
|
uint32_t x_int[4];
|
||||||
|
uint32_t x_fract[4];
|
||||||
|
lv_coord_t cir_size = 0;
|
||||||
|
x_int[0] = cp.x >> 2;
|
||||||
|
x_fract[0] = 0;
|
||||||
|
|
||||||
|
/*Calculate an 1/8 circle*/
|
||||||
|
while(circ_cont(&cp)) {
|
||||||
|
/*Calculate 4 point of the circle */
|
||||||
|
for(i = 0; i < 4; i++) {
|
||||||
|
circ_next(&cp, &tmp);
|
||||||
|
if(circ_cont(&cp) == false) break;
|
||||||
|
x_int[i] = cp.x >> 2;
|
||||||
|
x_fract[i] = cp.x & 0x3;
|
||||||
|
}
|
||||||
|
if(i != 4) break;
|
||||||
|
|
||||||
|
/*All lines on the same x when downscaled*/
|
||||||
|
if(x_int[0] == x_int[3]) {
|
||||||
|
cir_x[cir_size] = x_int[0];
|
||||||
|
cir_y[cir_size] = y_8th_cnt;
|
||||||
|
c->cir_opa[cir_size] = x_fract[0] + x_fract[1] + x_fract[2] + x_fract[3];
|
||||||
|
c->cir_opa[cir_size] *= 16;
|
||||||
|
cir_size++;
|
||||||
|
}
|
||||||
|
/*Second line on new x when downscaled*/
|
||||||
|
else if(x_int[0] != x_int[1]) {
|
||||||
|
cir_x[cir_size] = x_int[0];
|
||||||
|
cir_y[cir_size] = y_8th_cnt;
|
||||||
|
c->cir_opa[cir_size] = x_fract[0];
|
||||||
|
c->cir_opa[cir_size] *= 16;
|
||||||
|
cir_size++;
|
||||||
|
|
||||||
|
cir_x[cir_size] = x_int[0] - 1;
|
||||||
|
cir_y[cir_size] = y_8th_cnt;
|
||||||
|
c->cir_opa[cir_size] = 1 * 4 + x_fract[1] + x_fract[2] + x_fract[3];;
|
||||||
|
c->cir_opa[cir_size] *= 16;
|
||||||
|
cir_size++;
|
||||||
|
}
|
||||||
|
/*Third line on new x when downscaled*/
|
||||||
|
else if(x_int[0] != x_int[2]) {
|
||||||
|
cir_x[cir_size] = x_int[0];
|
||||||
|
cir_y[cir_size] = y_8th_cnt;
|
||||||
|
c->cir_opa[cir_size] = x_fract[0] + x_fract[1];
|
||||||
|
c->cir_opa[cir_size] *= 16;
|
||||||
|
cir_size++;
|
||||||
|
|
||||||
|
cir_x[cir_size] = x_int[0] - 1;
|
||||||
|
cir_y[cir_size] = y_8th_cnt;
|
||||||
|
c->cir_opa[cir_size] = 2 * 4 + x_fract[2] + x_fract[3];;
|
||||||
|
c->cir_opa[cir_size] *= 16;
|
||||||
|
cir_size++;
|
||||||
|
}
|
||||||
|
/*Forth line on new x when downscaled*/
|
||||||
|
else {
|
||||||
|
cir_x[cir_size] = x_int[0];
|
||||||
|
cir_y[cir_size] = y_8th_cnt;
|
||||||
|
c->cir_opa[cir_size] = x_fract[0] + x_fract[1] + x_fract[2];
|
||||||
|
c->cir_opa[cir_size] *= 16;
|
||||||
|
cir_size++;
|
||||||
|
|
||||||
|
cir_x[cir_size] = x_int[0] - 1;
|
||||||
|
cir_y[cir_size] = y_8th_cnt;
|
||||||
|
c->cir_opa[cir_size] = 3 * 4 + x_fract[3];;
|
||||||
|
c->cir_opa[cir_size] *= 16;
|
||||||
|
cir_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
y_8th_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*The point on the 1/8 circle is special, calculate it manually*/
|
||||||
|
int32_t mid = radius * 723;
|
||||||
|
int32_t mid_int = mid >> 10;
|
||||||
|
if(cir_x[cir_size-1] != mid_int || cir_y[cir_size-1] != mid_int) {
|
||||||
|
tmp = mid - (mid_int << 10);
|
||||||
|
if(tmp <= 512) {
|
||||||
|
tmp = tmp * tmp * 2;
|
||||||
|
tmp = tmp >> (10 + 6);
|
||||||
|
} else {
|
||||||
|
tmp = 1024 - tmp;
|
||||||
|
tmp = (int32_t)tmp * tmp * 2;
|
||||||
|
tmp = (int32_t)tmp >> (10 + 6);
|
||||||
|
tmp = 15 - tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
cir_x[cir_size] = mid_int;
|
||||||
|
cir_y[cir_size] = mid_int;
|
||||||
|
c->cir_opa[cir_size] = tmp;
|
||||||
|
c->cir_opa[cir_size] *= 16;
|
||||||
|
cir_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Build the second octet by mirroring the first*/
|
||||||
|
for(i = cir_size - 2; i >= 0; i--, cir_size++) {
|
||||||
|
cir_x[cir_size] = cir_y[i];
|
||||||
|
cir_y[cir_size] = cir_x[i];
|
||||||
|
c->cir_opa[cir_size] = c->cir_opa[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_coord_t y = 0;
|
||||||
|
i = 0;
|
||||||
|
c->opa_start_on_y[0] = 0;
|
||||||
|
while(i < cir_size) {
|
||||||
|
c->opa_start_on_y[y] = i;
|
||||||
|
c->x_start_on_y[y] = cir_x[i];
|
||||||
|
for(; cir_y[i] == y && i < (int32_t)cir_size; i++) {
|
||||||
|
c->x_start_on_y[y] = LV_MIN(c->x_start_on_y[y], cir_x[i]);
|
||||||
|
}
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_mem_buf_release(cir_x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_opa_t * get_next_line(_lv_draw_mask_radius_circle_dsc_t * c, lv_coord_t y, lv_coord_t * len, lv_coord_t * x_start)
|
||||||
|
{
|
||||||
|
*len = c->opa_start_on_y[y + 1] - c->opa_start_on_y[y];
|
||||||
|
*x_start = c->x_start_on_y[y];
|
||||||
|
return &c->cir_opa[c->opa_start_on_y[y]];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LV_ATTRIBUTE_FAST_MEM static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new)
|
LV_ATTRIBUTE_FAST_MEM static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new)
|
||||||
{
|
{
|
||||||
if(mask_new >= LV_OPA_MAX) return mask_act;
|
if(mask_new >= LV_OPA_MAX) return mask_act;
|
||||||
@@ -1220,24 +1347,5 @@ LV_ATTRIBUTE_FAST_MEM static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_
|
|||||||
return LV_UDIV255(mask_act * mask_new);// >> 8);
|
return LV_UDIV255(mask_act * mask_new);// >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Approximate the sqrt near to an already calculated value
|
|
||||||
* @param q store the result here
|
|
||||||
* @param ref the reference point (already calculated sqrt)
|
|
||||||
* @param x the value which sqrt should be approximated
|
|
||||||
*/
|
|
||||||
LV_ATTRIBUTE_FAST_MEM static inline void sqrt_approx(lv_sqrt_res_t * q, lv_sqrt_res_t * ref, uint32_t x)
|
|
||||||
{
|
|
||||||
x = x << 8; /*Upscale for extra precision*/
|
|
||||||
|
|
||||||
uint32_t raw = (ref->i << 4) + (ref->f >> 4);
|
|
||||||
uint32_t raw2 = raw * raw;
|
|
||||||
|
|
||||||
int32_t d = x - raw2;
|
|
||||||
d = (int32_t)d / (int32_t)(2 * raw) + raw;
|
|
||||||
|
|
||||||
q->i = d >> 4;
|
|
||||||
q->f = (d & 0xF) << 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /*LV_DRAW_COMPLEX*/
|
#endif /*LV_DRAW_COMPLEX*/
|
||||||
|
|||||||
@@ -147,6 +147,18 @@ typedef struct {
|
|||||||
uint16_t delta_deg;
|
uint16_t delta_deg;
|
||||||
} lv_draw_mask_angle_param_t;
|
} lv_draw_mask_angle_param_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t * buf;
|
||||||
|
lv_opa_t * cir_opa; /*Opacity of values on the circumference of an 1/4 circle*/
|
||||||
|
uint16_t * x_start_on_y; /*The x coordinate of the circle for each y value*/
|
||||||
|
uint16_t * opa_start_on_y; /*The index of `cir_opa` for each y value*/
|
||||||
|
int32_t life; /*How many times the entry way used*/
|
||||||
|
uint32_t used_cnt; /*Like a semaphore to count the referencing masks*/
|
||||||
|
lv_coord_t radius; /*The radius of the entry*/
|
||||||
|
} _lv_draw_mask_radius_circle_dsc_t;
|
||||||
|
|
||||||
|
typedef _lv_draw_mask_radius_circle_dsc_t _lv_draw_mask_radius_circle_dsc_arr_t[LV_CIRCLE_CACHE_SIZE];
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/*The first element must be the common descriptor*/
|
/*The first element must be the common descriptor*/
|
||||||
_lv_draw_mask_common_dsc_t dsc;
|
_lv_draw_mask_common_dsc_t dsc;
|
||||||
@@ -157,9 +169,8 @@ typedef struct {
|
|||||||
/*Invert the mask. 0: Keep the pixels inside.*/
|
/*Invert the mask. 0: Keep the pixels inside.*/
|
||||||
uint8_t outer: 1;
|
uint8_t outer: 1;
|
||||||
} cfg;
|
} cfg;
|
||||||
int32_t y_prev;
|
|
||||||
lv_sqrt_res_t y_prev_x;
|
|
||||||
|
|
||||||
|
_lv_draw_mask_radius_circle_dsc_t * circle;
|
||||||
} lv_draw_mask_radius_param_t;
|
} lv_draw_mask_radius_param_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -235,6 +246,21 @@ void * lv_draw_mask_remove_id(int16_t id);
|
|||||||
*/
|
*/
|
||||||
void * lv_draw_mask_remove_custom(void * custom_id);
|
void * lv_draw_mask_remove_custom(void * custom_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free the data from the parameter.
|
||||||
|
* It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom`
|
||||||
|
* Needs to be called only in special cases when the mask is not added by `lv_draw_mask_add`
|
||||||
|
* and not removed by `lv_draw_mask_remove_id` or `lv_draw_mask_remove_custom`
|
||||||
|
* @param p pointer to a mask parameter
|
||||||
|
*/
|
||||||
|
void lv_draw_mask_free_param(void * p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by LVGL the rendering of a screen is ready to clean up
|
||||||
|
* the temporal (cache) data of the masks
|
||||||
|
*/
|
||||||
|
void _lv_draw_mask_cleanup(void);
|
||||||
|
|
||||||
//! @cond Doxygen_Suppress
|
//! @cond Doxygen_Suppress
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_bg(const lv_area_t * coords, const lv_are
|
|||||||
y < coords_bg.y2 - rout - 1) {
|
y < coords_bg.y2 - rout - 1) {
|
||||||
mask_res = LV_DRAW_MASK_RES_FULL_COVER;
|
mask_res = LV_DRAW_MASK_RES_FULL_COVER;
|
||||||
if(simple_mode == false) {
|
if(simple_mode == false) {
|
||||||
lv_memset(mask_buf, opa, draw_area_w);
|
lv_memset(mask_buf, 0xff, draw_area_w);
|
||||||
mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h, draw_area_w);
|
mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h, draw_area_w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,7 +240,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_bg(const lv_area_t * coords, const lv_are
|
|||||||
|
|
||||||
/*If mask will taken into account its base opacity was already set by memset above*/
|
/*If mask will taken into account its base opacity was already set by memset above*/
|
||||||
if(mask_res == LV_DRAW_MASK_RES_CHANGED) {
|
if(mask_res == LV_DRAW_MASK_RES_CHANGED) {
|
||||||
opa2 = LV_OPA_COVER;
|
// opa2 = LV_OPA_COVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Get the current line color*/
|
/*Get the current line color*/
|
||||||
@@ -329,6 +329,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_bg(const lv_area_t * coords, const lv_are
|
|||||||
if(grad_map) lv_mem_buf_release(grad_map);
|
if(grad_map) lv_mem_buf_release(grad_map);
|
||||||
if(mask_buf) lv_mem_buf_release(mask_buf);
|
if(mask_buf) lv_mem_buf_release(mask_buf);
|
||||||
lv_draw_mask_remove_id(mask_rout_id);
|
lv_draw_mask_remove_id(mask_rout_id);
|
||||||
|
if(mask_rout_id != LV_MASK_ID_INV) lv_draw_mask_free_param(&mask_rout_param);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -509,8 +510,10 @@ LV_ATTRIBUTE_FAST_MEM static void draw_border(const lv_area_t * coords, const lv
|
|||||||
fill_area.y2++;
|
fill_area.y2++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
lv_draw_mask_free_param(&mask_rin_param);
|
||||||
|
lv_draw_mask_free_param(&mask_rout_param);
|
||||||
lv_draw_mask_remove_id(mask_rin_id);
|
lv_draw_mask_remove_id(mask_rin_id);
|
||||||
lv_draw_mask_remove_id(mask_rout_id);
|
if(mask_rout_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_rout_id);
|
||||||
lv_mem_buf_release(mask_buf);
|
lv_mem_buf_release(mask_buf);
|
||||||
}
|
}
|
||||||
#else /*LV_DRAW_COMPLEX*/
|
#else /*LV_DRAW_COMPLEX*/
|
||||||
@@ -1007,6 +1010,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(const lv_area_t * coords, const lv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lv_draw_mask_free_param(&mask_rout_param);
|
||||||
lv_draw_mask_remove_id(mask_rout_id);
|
lv_draw_mask_remove_id(mask_rout_id);
|
||||||
lv_mem_buf_release(mask_buf);
|
lv_mem_buf_release(mask_buf);
|
||||||
lv_mem_buf_release(sh_buf);
|
lv_mem_buf_release(sh_buf);
|
||||||
@@ -1064,6 +1068,8 @@ LV_ATTRIBUTE_FAST_MEM static void shadow_draw_corner_buf(const lv_area_t * coord
|
|||||||
}
|
}
|
||||||
lv_mem_buf_release(mask_line);
|
lv_mem_buf_release(mask_line);
|
||||||
|
|
||||||
|
lv_draw_mask_free_param(&mask_param);
|
||||||
|
|
||||||
if(sw == 1) {
|
if(sw == 1) {
|
||||||
int32_t i;
|
int32_t i;
|
||||||
lv_opa_t * res_buf = (lv_opa_t *)sh_buf;
|
lv_opa_t * res_buf = (lv_opa_t *)sh_buf;
|
||||||
@@ -1394,6 +1400,8 @@ static void draw_full_border(const lv_area_t * area_inner, const lv_area_t * are
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lv_draw_mask_free_param(&mask_rin_param);
|
||||||
|
lv_draw_mask_free_param(&mask_rout_param);
|
||||||
lv_draw_mask_remove_id(mask_rin_id);
|
lv_draw_mask_remove_id(mask_rin_id);
|
||||||
lv_draw_mask_remove_id(mask_rout_id);
|
lv_draw_mask_remove_id(mask_rout_id);
|
||||||
lv_mem_buf_release(mask_buf);
|
lv_mem_buf_release(mask_buf);
|
||||||
|
|||||||
@@ -287,6 +287,8 @@ static void draw_disc_grad(lv_event_t * e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if LV_DRAW_COMPLEX
|
#if LV_DRAW_COMPLEX
|
||||||
|
lv_draw_mask_free_param(&mask_out_param);
|
||||||
|
lv_draw_mask_free_param(&mask_in_param);
|
||||||
lv_draw_mask_remove_id(mask_out_id);
|
lv_draw_mask_remove_id(mask_out_id);
|
||||||
lv_draw_mask_remove_id(mask_in_id);
|
lv_draw_mask_remove_id(mask_in_id);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -414,7 +414,7 @@ static void draw_ticks_and_labels(lv_obj_t * obj, const lv_area_t * clip_area, c
|
|||||||
lv_draw_mask_radius_init(&outer_mask, &area_outer, LV_RADIUS_CIRCLE, false);
|
lv_draw_mask_radius_init(&outer_mask, &area_outer, LV_RADIUS_CIRCLE, false);
|
||||||
int16_t outer_mask_id = lv_draw_mask_add(&outer_mask, NULL);
|
int16_t outer_mask_id = lv_draw_mask_add(&outer_mask, NULL);
|
||||||
|
|
||||||
int16_t inner_act_mask_id = -1; /*Will be added later*/
|
int16_t inner_act_mask_id = LV_MASK_ID_INV; /*Will be added later*/
|
||||||
|
|
||||||
uint32_t minor_cnt = scale->tick_major_nth ? scale->tick_major_nth - 1 : 0xFFFF;
|
uint32_t minor_cnt = scale->tick_major_nth ? scale->tick_major_nth - 1 : 0xFFFF;
|
||||||
for(i = 0; i < scale->tick_cnt; i++) {
|
for(i = 0; i < scale->tick_cnt; i++) {
|
||||||
@@ -530,6 +530,9 @@ static void draw_ticks_and_labels(lv_obj_t * obj, const lv_area_t * clip_area, c
|
|||||||
line_dsc.width = line_width_ori;
|
line_dsc.width = line_width_ori;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
lv_draw_mask_free_param(&inner_minor_mask);
|
||||||
|
lv_draw_mask_free_param(&inner_major_mask);
|
||||||
|
lv_draw_mask_free_param(&outer_mask);
|
||||||
lv_draw_mask_remove_id(outer_mask_id);
|
lv_draw_mask_remove_id(outer_mask_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -250,6 +250,19 @@
|
|||||||
# define LV_SHADOW_CACHE_SIZE 0
|
# define LV_SHADOW_CACHE_SIZE 0
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Set number of maximally cached circle data.
|
||||||
|
* The circumference of 1/4 circle are saved for anti-aliasing
|
||||||
|
* radius * 4 bytes are used per circle (the most often used radiuses are saved)
|
||||||
|
* 0: to disable caching */
|
||||||
|
#ifndef LV_CIRCLE_CACHE_SIZE
|
||||||
|
# ifdef CONFIG_LV_CIRCLE_CACHE_SIZE
|
||||||
|
# define LV_CIRCLE_CACHE_SIZE CONFIG_LV_CIRCLE_CACHE_SIZE
|
||||||
|
# else
|
||||||
|
# define LV_CIRCLE_CACHE_SIZE 4
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /*LV_DRAW_COMPLEX*/
|
#endif /*LV_DRAW_COMPLEX*/
|
||||||
|
|
||||||
/*Default image cache size. Image caching keeps the images opened.
|
/*Default image cache size. Image caching keeps the images opened.
|
||||||
|
|||||||
@@ -459,7 +459,15 @@ static inline uint32_t lv_color_to32(lv_color_t color)
|
|||||||
LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix)
|
LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix)
|
||||||
{
|
{
|
||||||
lv_color_t ret;
|
lv_color_t ret;
|
||||||
#if LV_COLOR_DEPTH != 1
|
|
||||||
|
#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 result = ((((fg - bg) * mix) >> 5) + bg) & 0x7E0F81F;
|
||||||
|
ret.full = (uint16_t)((result >> 16) | result);
|
||||||
|
#elif LV_COLOR_DEPTH != 1
|
||||||
/*LV_COLOR_DEPTH == 8, 16 or 32*/
|
/*LV_COLOR_DEPTH == 8, 16 or 32*/
|
||||||
LV_COLOR_SET_R(ret, LV_UDIV255((uint16_t) LV_COLOR_GET_R(c1) * mix + LV_COLOR_GET_R(c2) *
|
LV_COLOR_SET_R(ret, LV_UDIV255((uint16_t) LV_COLOR_GET_R(c1) * mix + LV_COLOR_GET_R(c2) *
|
||||||
(255 - mix) + LV_COLOR_MIX_ROUND_OFS));
|
(255 - mix) + LV_COLOR_MIX_ROUND_OFS));
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ extern "C" {
|
|||||||
LV_DISPATCH_COND(f, _lv_img_cache_entry_t, _lv_img_cache_single, LV_IMG_CACHE_DEF, 0) \
|
LV_DISPATCH_COND(f, _lv_img_cache_entry_t, _lv_img_cache_single, LV_IMG_CACHE_DEF, 0) \
|
||||||
LV_DISPATCH(f, lv_timer_t*, _lv_timer_act) \
|
LV_DISPATCH(f, lv_timer_t*, _lv_timer_act) \
|
||||||
LV_DISPATCH(f, lv_mem_buf_arr_t , lv_mem_buf) \
|
LV_DISPATCH(f, lv_mem_buf_arr_t , lv_mem_buf) \
|
||||||
|
LV_DISPATCH_COND(f, _lv_draw_mask_radius_circle_dsc_arr_t , _lv_circle_cache, LV_DRAW_COMPLEX, 1) \
|
||||||
LV_DISPATCH_COND(f, _lv_draw_mask_saved_arr_t , _lv_draw_mask_list, LV_DRAW_COMPLEX, 1) \
|
LV_DISPATCH_COND(f, _lv_draw_mask_saved_arr_t , _lv_draw_mask_list, LV_DRAW_COMPLEX, 1) \
|
||||||
LV_DISPATCH(f, void * , _lv_theme_default_styles) \
|
LV_DISPATCH(f, void * , _lv_theme_default_styles) \
|
||||||
LV_DISPATCH_COND(f, uint8_t *, _lv_font_decompr_buf, LV_USE_FONT_COMPRESSED, 1)
|
LV_DISPATCH_COND(f, uint8_t *, _lv_font_decompr_buf, LV_USE_FONT_COMPRESSED, 1)
|
||||||
|
|||||||
@@ -486,6 +486,8 @@ static void draw_indic(lv_event_t * e)
|
|||||||
lv_draw_rect(&bar->indic_area, clip_area, &draw_rect_dsc);
|
lv_draw_rect(&bar->indic_area, clip_area, &draw_rect_dsc);
|
||||||
|
|
||||||
#if LV_DRAW_COMPLEX
|
#if LV_DRAW_COMPLEX
|
||||||
|
lv_draw_mask_free_param(&mask_indic_param);
|
||||||
|
lv_draw_mask_free_param(&mask_bg_param);
|
||||||
lv_draw_mask_remove_id(mask_indic_id);
|
lv_draw_mask_remove_id(mask_indic_id);
|
||||||
lv_draw_mask_remove_id(mask_bg_id);
|
lv_draw_mask_remove_id(mask_bg_id);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 17 KiB |
Reference in New Issue
Block a user