feat(blur): add blur support (#9223)
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Compare file templates with file names / template-check (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Install LVGL using CMake / build-examples (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/benchmark_results_comment/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/filter_docker_logs/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/serialize_results/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 32b - lv_conf_perf32b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 64b - lv_conf_perf64b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Save PR Number (push) Has been cancelled
Hardware Performance Test / Hardware Performance Benchmark (push) Has been cancelled
Hardware Performance Test / HW Benchmark - Save PR Number (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
Gabor Kiss-Vamosi
2025-11-27 18:21:06 +01:00
committed by GitHub
parent 4bf24d9944
commit e54d668633
64 changed files with 1348 additions and 130 deletions
@@ -1408,6 +1408,48 @@ Sets the intensity of color mixing. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Ext. draw</strong> No</li>
</ul>
blur_radius
~~~~~~~~~~~
Sets the intensity of blurring. Applied on each lv_part separately before the children are rendered.
.. raw:: html
<ul>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Default</strong> `0`</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Inherited</strong> No</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Layout</strong> No</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Ext. draw</strong> No</li>
</ul>
blur_backdrop
~~~~~~~~~~~~~
If `true` the background of the widget will be blurred. The part should have < 100% opacity to make it visible. If `false` the given part will be blurred when it's rendered but before drawing the children.
.. raw:: html
<ul>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Default</strong> `false`</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Inherited</strong> No</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Layout</strong> No</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Ext. draw</strong> No</li>
</ul>
blur_quality
~~~~~~~~~~~~
Setting to `LV_BLUR_QUALITY_SPEED` the blurring algorithm will prefer speed over quality. `LV_BLUR_QUALITY_PRECISION` will force using higher quality but slower blur. With `LV_BLUR_QUALITY_AUTO` the quality will be selected automatically.
.. raw:: html
<ul>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Default</strong> `LV_BLUR_QUALITY_AUTO`</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Inherited</strong> No</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Layout</strong> No</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Ext. draw</strong> No</li>
</ul>
anim
~~~~
@@ -617,6 +617,25 @@ Functions for triangle drawing:
Blur Draw Descriptor
********************
Blur is defined by :cpp:type:`lv_draw_blur_dsc_t`, which includes:
:blur_radius: The radius of the blur.
:corner_radius: The radius of the corners.
:quality: Tells whether to prefer speed or quality.
Functions for blur drawing:
- :cpp:expr:`lv_draw_blur_dsc_init(&dsc)` initializes a blur descriptor.
- :cpp:expr:`lv_draw_blur(layer, &dsc, area)` creates a task to blur an area.
- :cpp:expr:`lv_draw_task_get_blur_dsc(draw_task)` retrieves blur descriptor.
.. lv_example:: widgets/canvas/lv_example_canvas_10
:language: c
Vector Draw Descriptor
**********************
+12 -4
View File
@@ -57,14 +57,22 @@ Draw a triangle to the canvas
.. lv_example:: widgets/canvas/lv_example_canvas_9
:language: c
Draw Fancy Letter Effects
-------------------------
Blur an area on the canvas
-----------------------------
.. lv_example:: widgets/canvas/lv_example_canvas_10
:language: c
Draw Fancy Letter Effects 2
---------------------------
Draw Fancy Letter Effects
-------------------------
.. lv_example:: widgets/canvas/lv_example_canvas_11
:language: c
Draw Fancy Letter Effects 2
---------------------------
.. lv_example:: widgets/canvas/lv_example_canvas_12
:language: c
+54 -52
View File
@@ -1,67 +1,69 @@
#include "../../lv_examples.h"
#if LV_USE_CANVAS && LV_BUILD_EXAMPLES
#if LV_USE_CANVAS && LV_FONT_MONTSERRAT_18 && LV_BUILD_EXAMPLES
#define CANVAS_WIDTH 300
#define CANVAS_HEIGHT 200
static void timer_cb(lv_timer_t * timer)
{
static int16_t counter = 0;
const char * string = "lol~ I'm wavvvvvvving~>>>";
const int16_t string_len = lv_strlen(string);
lv_obj_t * canvas = (lv_obj_t *)lv_timer_get_user_data(timer);
lv_layer_t layer;
lv_canvas_init_layer(canvas, &layer);
lv_canvas_fill_bg(canvas, lv_color_white(), LV_OPA_COVER);
lv_draw_letter_dsc_t letter_dsc;
lv_draw_letter_dsc_init(&letter_dsc);
letter_dsc.color = lv_color_hex(0xff0000);
letter_dsc.font = lv_font_get_default();
{
#define CURVE2_X(t) (t * 2 + 10)
#define CURVE2_Y(t) (lv_trigo_sin((t) * 5) * 40 / 32767 + CANVAS_HEIGHT / 2)
int32_t pre_x = CURVE2_X(-1);
int32_t pre_y = CURVE2_Y(-1);
for(int16_t i = 0; i < string_len; i++) {
const int16_t angle = (int16_t)(i * 5);
const int32_t x = CURVE2_X(angle);
const int32_t y = CURVE2_Y(angle + counter / 2);
const lv_point_t point = { .x = x, .y = y };
letter_dsc.unicode = (uint32_t)string[i % string_len];
letter_dsc.rotation = lv_atan2(y - pre_y, x - pre_x) * 10;
letter_dsc.color = lv_color_hsv_to_rgb(i * 10, 100, 100);
lv_draw_letter(&layer, &letter_dsc, &point);
pre_x = x;
pre_y = y;
}
}
lv_canvas_finish_layer(canvas, &layer);
counter++;
}
#define CANVAS_WIDTH 100
#define CANVAS_HEIGHT 100
/**
*Blur an area on the canvas
*/
void lv_example_canvas_10(void)
{
/*Create a buffer for the canvas*/
LV_DRAW_BUF_DEFINE_STATIC(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
LV_DRAW_BUF_DEFINE_STATIC(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_RGB565);
LV_DRAW_BUF_INIT_STATIC(draw_buf);
/*Create a canvas and initialize its palette*/
lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_obj_set_size(canvas, CANVAS_WIDTH, CANVAS_HEIGHT);
lv_canvas_set_draw_buf(canvas, &draw_buf);
lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER);
lv_obj_center(canvas);
lv_canvas_set_draw_buf(canvas, &draw_buf);
lv_layer_t layer;
lv_canvas_init_layer(canvas, &layer);
lv_timer_create(timer_cb, 16, canvas);
/*A label in the background*/
lv_draw_label_dsc_t label_dsc;
lv_draw_label_dsc_init(&label_dsc);
label_dsc.color = lv_palette_main(LV_PALETTE_RED);
label_dsc.font = &lv_font_montserrat_14;
label_dsc.decor = LV_TEXT_DECOR_UNDERLINE;
label_dsc.align = LV_TEXT_ALIGN_CENTER;
label_dsc.text = "Some parts of\nthis canvas is blurred";
lv_area_t label1_coords = {10, 10, 90, 90};
lv_draw_label(&layer, &label_dsc, &label1_coords);
/*Blur the middle of the canvas*/
lv_draw_blur_dsc_t blur_dsc;
lv_draw_blur_dsc_init(&blur_dsc);
blur_dsc.corner_radius = 10;
blur_dsc.blur_radius = 8;
lv_area_t fill_coords = {20, 30, 80, 70};
lv_draw_blur(&layer, &blur_dsc, &fill_coords);
/*Draw a semi-transparent rectangle on the blurred area*/
lv_draw_fill_dsc_t fill_dsc;
lv_draw_fill_dsc_init(&fill_dsc);
fill_dsc.color = lv_palette_lighten(LV_PALETTE_BLUE, 1);
fill_dsc.radius = 10;
fill_dsc.opa = LV_OPA_30;
lv_draw_fill(&layer, &fill_dsc, &fill_coords);
/*Add label on the blurred area*/
lv_draw_label_dsc_init(&label_dsc);
label_dsc.color = lv_color_black();
label_dsc.font = &lv_font_montserrat_14;
label_dsc.align = LV_TEXT_ALIGN_CENTER;
label_dsc.text = "Hello world";
lv_area_t label2_coords = {20, 35, 80, 60};
lv_draw_label(&layer, &label_dsc, &label2_coords);
lv_canvas_finish_layer(canvas, &layer);
}
#endif
+9 -11
View File
@@ -7,10 +7,10 @@
static void timer_cb(lv_timer_t * timer)
{
static int32_t counter = 0;
const char * string = "windstorrrrrrrrrrrrrrrrm~>>>";
const char * string = "lol~ I'm wavvvvvvving~>>>";
const int16_t string_len = lv_strlen(string);
lv_obj_t * canvas = (lv_obj_t *) lv_timer_get_user_data(timer);
lv_obj_t * canvas = (lv_obj_t *)lv_timer_get_user_data(timer);
lv_layer_t layer;
lv_canvas_init_layer(canvas, &layer);
@@ -22,23 +22,21 @@ static void timer_cb(lv_timer_t * timer)
letter_dsc.font = lv_font_get_default();
{
#define CURVE2_X(t) ((t) * 2 + lv_trigo_cos((t) * 5) * 40 / 32767 - 10)
#define CURVE2_Y(t, T) ((t) * lv_trigo_sin(((t) + (T)) * 5) * 40 / 32767 / 80 + CANVAS_HEIGHT / 2)
#define CURVE2_X(t) (t * 2 + 10)
#define CURVE2_Y(t) (lv_trigo_sin((t) * 5) * 40 / 32767 + CANVAS_HEIGHT / 2)
int32_t pre_x = CURVE2_X(-1);
int32_t pre_y = CURVE2_Y(-1, 0);
int32_t pre_y = CURVE2_Y(-1);
for(int16_t i = 0; i < string_len; i++) {
const int32_t angle = i * 5;
const int16_t angle = (int16_t)(i * 5);
const int32_t x = CURVE2_X(angle);
const int32_t y = CURVE2_Y(angle + 30, counter / 2);
const int32_t y = CURVE2_Y(angle + counter / 2);
const lv_point_t point = { .x = x, .y = y };
letter_dsc.unicode = (uint32_t)string[i % string_len];
letter_dsc.rotation = lv_atan2(y - pre_y, x - pre_x) * 10;
letter_dsc.color = lv_color_hsv_to_rgb(i * 10, 100, 100);
lv_point_t p = (lv_point_t) {
.x = x, .y = y
};
lv_draw_letter(&layer, &letter_dsc, &p);
lv_draw_letter(&layer, &letter_dsc, &point);
pre_x = x;
pre_y = y;
@@ -0,0 +1,69 @@
#include "../../lv_examples.h"
#if LV_USE_CANVAS && LV_BUILD_EXAMPLES
#define CANVAS_WIDTH 300
#define CANVAS_HEIGHT 200
static void timer_cb(lv_timer_t * timer)
{
static int32_t counter = 0;
const char * string = "windstorrrrrrrrrrrrrrrrm~>>>";
const int16_t string_len = lv_strlen(string);
lv_obj_t * canvas = (lv_obj_t *) lv_timer_get_user_data(timer);
lv_layer_t layer;
lv_canvas_init_layer(canvas, &layer);
lv_canvas_fill_bg(canvas, lv_color_white(), LV_OPA_COVER);
lv_draw_letter_dsc_t letter_dsc;
lv_draw_letter_dsc_init(&letter_dsc);
letter_dsc.color = lv_color_hex(0xff0000);
letter_dsc.font = lv_font_get_default();
{
#define CURVE2_X(t) ((t) * 2 + lv_trigo_cos((t) * 5) * 40 / 32767 - 10)
#define CURVE2_Y(t, T) ((t) * lv_trigo_sin(((t) + (T)) * 5) * 40 / 32767 / 80 + CANVAS_HEIGHT / 2)
int32_t pre_x = CURVE2_X(-1);
int32_t pre_y = CURVE2_Y(-1, 0);
for(int16_t i = 0; i < string_len; i++) {
const int32_t angle = i * 5;
const int32_t x = CURVE2_X(angle);
const int32_t y = CURVE2_Y(angle + 30, counter / 2);
letter_dsc.unicode = (uint32_t)string[i % string_len];
letter_dsc.rotation = lv_atan2(y - pre_y, x - pre_x) * 10;
letter_dsc.color = lv_color_hsv_to_rgb(i * 10, 100, 100);
lv_point_t p = (lv_point_t) {
.x = x, .y = y
};
lv_draw_letter(&layer, &letter_dsc, &p);
pre_x = x;
pre_y = y;
}
}
lv_canvas_finish_layer(canvas, &layer);
counter++;
}
void lv_example_canvas_12(void)
{
/*Create a buffer for the canvas*/
LV_DRAW_BUF_DEFINE_STATIC(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
LV_DRAW_BUF_INIT_STATIC(draw_buf);
lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_obj_set_size(canvas, CANVAS_WIDTH, CANVAS_HEIGHT);
lv_obj_center(canvas);
lv_canvas_set_draw_buf(canvas, &draw_buf);
lv_timer_create(timer_cb, 16, canvas);
}
#endif
+2
View File
@@ -63,6 +63,7 @@ void lv_example_canvas_8(void);
void lv_example_canvas_9(void);
void lv_example_canvas_10(void);
void lv_example_canvas_11(void);
void lv_example_canvas_12(void);
void lv_example_chart_1(void);
void lv_example_chart_2(void);
@@ -118,6 +119,7 @@ void lv_example_menu_5(void);
void lv_example_msgbox_1(void);
void lv_example_msgbox_2(void);
void lv_example_msgbox_3(void);
void lv_example_obj_1(void);
void lv_example_obj_2(void);
+6
View File
@@ -11,4 +11,10 @@ Scrolling and styled Message box
.. lv_example:: widgets/msgbox/lv_example_msgbox_2
:language: c
Message box with blurred background
-----------------------------------
.. lv_example:: widgets/msgbox/lv_example_msgbox_3
:language: c
@@ -0,0 +1,75 @@
#include "../../lv_examples.h"
#if LV_USE_MSGBOX && LV_BUILD_EXAMPLES
static void dropdown_value_changed_event_cb(lv_event_t * e)
{
lv_obj_t * dropdown = lv_event_get_target_obj(e);
lv_obj_t * msgbox = (lv_obj_t *)lv_event_get_user_data(e);
lv_obj_t * top_layer = lv_layer_top();
uint32_t opt = lv_dropdown_get_selected(dropdown);
/*Blur screen*/
if(opt == 0) {
lv_obj_set_style_blur_radius(msgbox, 0, 0);
lv_obj_set_style_blur_radius(top_layer, 24, 0);
}
/*Blur Message box*/
else {
lv_obj_set_style_blur_radius(msgbox, 24, 0);
lv_obj_set_style_blur_radius(top_layer, 0, 0);
}
}
void lv_example_msgbox_3(void)
{
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
" Ut orci mauris, placerat et euismod eu, ullamcorper eget massa. "
"Suspendisse sodales vitae augue ut vestibulum. "
"Nunc fringilla leo ut tellus consectetur tincidunt. "
"Quisque eu tortor semper odio aliquet congue egestas ac massa. "
"Phasellus elit lectus, finibus tempor augue in, elementum lobortis nisl. "
"Donec tristique lorem et tincidunt faucibus.\n\n"
"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
" Ut orci mauris, placerat et euismod eu, ullamcorper eget massa. "
"Suspendisse sodales vitae augue ut vestibulum. "
"Nunc fringilla leo ut tellus consectetur tincidunt. "
"Quisque eu tortor semper odio aliquet congue egestas ac massa. "
"Phasellus elit lectus, finibus tempor augue in, elementum lobortis nisl. "
"Donec tristique lorem et tincidunt faucibus.");
lv_obj_set_width(label, lv_pct(60));
lv_obj_center(label);
lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_BLUE), 0);
lv_obj_t * msgbox1 = lv_msgbox_create(lv_layer_top());
lv_msgbox_add_title(msgbox1, "Setting");
lv_msgbox_add_text(msgbox1, "Hello!\n\n"
"Scroll the text in the background to see how it behaves.");
/*Just a little styling on the message box*/
lv_obj_set_style_bg_opa(msgbox1, LV_OPA_40, 0);
lv_obj_set_style_bg_opa(lv_msgbox_get_header(msgbox1), LV_OPA_50, 0);
lv_obj_set_style_bg_color(lv_msgbox_get_header(msgbox1), lv_color_black(), 0);
lv_obj_set_style_bg_color(msgbox1, lv_color_black(), 0);
lv_obj_set_style_text_color(msgbox1, lv_color_white(), 0);
lv_obj_set_style_text_color(lv_msgbox_get_header(msgbox1), lv_color_white(), 0);
lv_obj_set_style_blur_backdrop(msgbox1, true, 0);
/*A dropdown to select what to blur*/
lv_obj_t * dropdown = lv_dropdown_create(lv_layer_top());
lv_dropdown_set_options(dropdown, "Blur screen\nBlur msgbox");
lv_obj_set_pos(dropdown, 5, 5);
lv_obj_add_event_cb(dropdown, dropdown_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, msgbox1);
/*Also make the list blurred*/
lv_obj_set_style_blur_radius(lv_dropdown_get_list(dropdown), 24, 0);
lv_obj_set_style_blur_backdrop(lv_dropdown_get_list(dropdown), true, 0);
lv_obj_set_style_bg_opa(lv_dropdown_get_list(dropdown), LV_OPA_50, 0);
/*Send a value changed event to set the initial state*/
lv_obj_send_event(dropdown, LV_EVENT_VALUE_CHANGED, NULL);
}
#endif
+12
View File
@@ -401,6 +401,18 @@ props = [
'style_type': 'num', 'var_type': 'lv_opa_t', 'default':'`LV_OPA_TRANSP`', 'inherited': 0, 'layout': 0, 'ext_draw': 0,
'dsc': "Sets the intensity of color mixing. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent. A value of 255, `LV_OPA_100` or `LV_OPA_COVER` means fully opaque. Intermediate values like LV_OPA_10, LV_OPA_20, etc result in semi-transparency."},
{'name': 'BLUR_RADIUS',
'style_type': 'num', 'var_type': 'int32_t', 'default':'`0`', 'inherited': 0, 'layout': 0, 'ext_draw': 0,
'dsc': "Sets the intensity of blurring. Applied on each lv_part separately before the children are rendered."},
{'name': 'BLUR_BACKDROP',
'style_type': 'num', 'var_type': 'bool', 'default':'`false`', 'inherited': 0, 'layout': 0, 'ext_draw': 0,
'dsc': "If `true` the background of the widget will be blurred. The part should have < 100% opacity to make it visible. If `false` the given part will be blurred when it's rendered but before drawing the children."},
{'name': 'BLUR_QUALITY',
'style_type': 'num', 'var_type': 'lv_blur_quality_t', 'default':'`LV_BLUR_QUALITY_AUTO`', 'inherited': 0, 'layout': 0, 'ext_draw': 0,
'dsc': "Setting to `LV_BLUR_QUALITY_SPEED` the blurring algorithm will prefer speed over quality. `LV_BLUR_QUALITY_PRECISION` will force using higher quality but slower blur. With `LV_BLUR_QUALITY_AUTO` the quality will be selected automatically. "},
{'name': 'ANIM',
'style_type': 'ptr', 'var_type': 'const lv_anim_t *', 'default':'`NULL`', 'inherited': 0, 'layout': 0, 'ext_draw': 0,
'dsc': "Animation template for Widget's animation. Should be a pointer to `lv_anim_t`. The animation parameters are widget specific, e.g. animation time could be the E.g. blink time of the cursor on the Text Area or scroll time of a roller. See Widgets' documentation to learn more."},
+36 -6
View File
@@ -693,10 +693,20 @@ static void lv_obj_draw(lv_event_t * e)
}
else if(code == LV_EVENT_DRAW_MAIN) {
lv_layer_t * layer = lv_event_get_layer(e);
lv_draw_rect_dsc_t draw_dsc;
lv_draw_rect_dsc_init(&draw_dsc);
draw_dsc.base.layer = layer;
lv_draw_blur_dsc_t blur_dsc;
lv_draw_blur_dsc_init(&blur_dsc);
blur_dsc.corner_radius = draw_dsc.radius;
bool backdrop_blur = lv_obj_get_style_blur_backdrop(obj, LV_PART_INDICATOR);
lv_obj_init_draw_blur_dsc(obj, LV_PART_MAIN, &blur_dsc);
blur_dsc.base.layer = layer;
if(backdrop_blur) lv_draw_blur(layer, &blur_dsc, &obj->coords);
lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &draw_dsc);
/*If the border is drawn later disable loading its properties*/
if(lv_obj_get_style_border_post(obj, LV_PART_MAIN)) {
@@ -710,6 +720,9 @@ static void lv_obj_draw(lv_event_t * e)
lv_area_increase(&coords, w, h);
lv_draw_rect(layer, &draw_dsc, &coords);
blur_dsc.blur_radius = lv_obj_get_style_blur_radius(obj, LV_PART_MAIN);
if(!backdrop_blur) lv_draw_blur(layer, &blur_dsc, &coords);
}
else if(code == LV_EVENT_DRAW_POST) {
lv_layer_t * layer = lv_event_get_layer(e);
@@ -747,17 +760,34 @@ static void draw_scrollbar(lv_obj_t * obj, lv_layer_t * layer)
if(lv_area_get_size(&hor_area) <= 0 && lv_area_get_size(&ver_area) <= 0) return;
lv_draw_rect_dsc_t draw_dsc;
lv_result_t sb_res = scrollbar_init_draw_dsc(obj, &draw_dsc);
lv_draw_rect_dsc_t rect_dsc;
lv_result_t sb_res = scrollbar_init_draw_dsc(obj, &rect_dsc);
if(sb_res != LV_RESULT_OK) return;
bool backdrop_blur = lv_obj_get_style_blur_backdrop(obj, LV_PART_SCROLLBAR);
lv_draw_blur_dsc_t blur_dsc;
lv_draw_blur_dsc_init(&blur_dsc);
blur_dsc.corner_radius = rect_dsc.radius;
blur_dsc.blur_radius = lv_obj_get_style_blur_radius(obj, LV_PART_SCROLLBAR);
if(lv_area_get_size(&hor_area) > 0) {
draw_dsc.base.id1 = 0;
lv_draw_rect(layer, &draw_dsc, &hor_area);
if(backdrop_blur) lv_obj_init_draw_blur_dsc(obj, LV_PART_SCROLLBAR, &blur_dsc);
blur_dsc.base.id1 = 0;
lv_draw_blur(layer, &blur_dsc, &hor_area);
rect_dsc.base.id1 = 0;
lv_draw_rect(layer, &rect_dsc, &hor_area);
if(!backdrop_blur) lv_draw_blur(layer, &blur_dsc, &hor_area);
}
if(lv_area_get_size(&ver_area) > 0) {
draw_dsc.base.id1 = 1;
lv_draw_rect(layer, &draw_dsc, &ver_area);
blur_dsc.base.id1 = 1;
if(backdrop_blur) lv_draw_blur(layer, &blur_dsc, &ver_area);
rect_dsc.base.id1 = 1;
lv_draw_rect(layer, &rect_dsc, &ver_area);
if(!backdrop_blur) lv_draw_blur(layer, &blur_dsc, &ver_area);
}
}
+18 -1
View File
@@ -12,7 +12,6 @@
#include "../display/lv_display.h"
#include "../indev/lv_indev.h"
#include "../stdlib/lv_string.h"
#include "../draw/lv_draw_arc.h"
/*********************
* DEFINES
@@ -319,6 +318,24 @@ void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_arc_dsc_t
LV_PROFILER_DRAW_END;
}
void lv_obj_init_draw_blur_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_blur_dsc_t * draw_dsc)
{
LV_PROFILER_DRAW_BEGIN;
draw_dsc->base.obj = obj;
draw_dsc->base.part = part;
draw_dsc->blur_radius = lv_obj_get_style_blur_radius(obj, part);
draw_dsc->quality = lv_obj_get_style_blur_quality(obj, part);
/*Radius might be set earlier as it's already known*/
if(draw_dsc->corner_radius == 0) {
draw_dsc->corner_radius = lv_obj_get_style_radius(obj, part);
}
LV_PROFILER_DRAW_END;
}
int32_t lv_obj_calculate_ext_draw_size(lv_obj_t * obj, lv_part_t part)
{
LV_PROFILER_DRAW_BEGIN;
+13
View File
@@ -20,6 +20,7 @@ extern "C" {
#include "../draw/lv_draw_line.h"
#include "../draw/lv_draw_arc.h"
#include "../draw/lv_draw_triangle.h"
#include "../draw/lv_draw_blur.h"
#include "lv_obj_style.h"
/*********************
@@ -103,6 +104,18 @@ void lv_obj_init_draw_line_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_line_dsc_
*/
void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_arc_dsc_t * draw_dsc);
/**
* Initialize a blur draw descriptor from an object's styles in its current state.
* draw_dsc->radius will only be calculated if it's 0 initially. Radius can be set before calling this function
* to avoid getting it twice.
* @param obj pointer to an object
* @param part part of the object, e.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc
* @param draw_dsc the descriptor to initialize.
* Should be initialized with `lv_draw_blur_dsc_init(draw_dsc)`.
*/
void lv_obj_init_draw_blur_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_blur_dsc_t * draw_dsc);
/**
* Get the required extra size (around the object's part) to draw shadow, outline, value etc.
* @param obj pointer to an object
+105 -20
View File
@@ -36,6 +36,8 @@ static void layout_update_core(lv_obj_t * obj);
static void transform_point_array(const lv_obj_t * obj, lv_point_t * p, size_t p_count, bool inv);
static bool is_transformed(const lv_obj_t * obj);
static lv_obj_tree_walk_res_t update_layout_completed_cb(lv_obj_t * obj, void * user_data);
static lv_result_t invalidate_area_core(const lv_obj_t * obj, lv_area_t * area_tmp);
/**********************
* STATIC VARIABLES
**********************/
@@ -860,35 +862,94 @@ void lv_obj_get_transformed_area(const lv_obj_t * obj, lv_area_t * area, lv_obj_
area->y2 = LV_MAX4(p[0].y, p[1].y, p[2].y, p[3].y);
}
void lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area)
typedef struct {
const lv_obj_t * requester_obj;
const lv_area_t * inv_area;
} blur_walk_data_t;
static lv_obj_tree_walk_res_t blur_walk_cb(lv_obj_t * obj, void * user_data)
{
blur_walk_data_t * blur_data = user_data;
if(obj == blur_data->requester_obj) return LV_OBJ_TREE_WALK_SKIP_CHILDREN;
/*Truncate the area to the object*/
lv_area_t obj_coords;
int32_t ext_size = lv_obj_get_ext_draw_size(obj);
lv_area_copy(&obj_coords, &obj->coords);
lv_area_increase(&obj_coords, ext_size, ext_size);
if(is_transformed(obj)) {
lv_obj_get_transformed_area(obj, &obj_coords, LV_OBJ_POINT_TRANSFORM_FLAG_RECURSIVE);
}
/*If the widget has blur set, invalidate it*/
if(lv_area_is_on(blur_data->inv_area, &obj_coords)) {
const uint32_t group = (uint32_t)1 << lv_style_get_prop_group(LV_STYLE_BLUR_RADIUS);
const lv_state_t state = lv_obj_style_get_selector_state(lv_obj_get_state(obj));
const lv_state_t state_inv = ~state;
lv_style_value_t v;
uint32_t i;
for(i = 0; i < obj->style_cnt; i++) {
lv_obj_style_t * obj_style = &obj->styles[i];
if(obj_style->is_disabled) continue;
if((obj_style->style->has_group & group) == 0) continue;
lv_state_t state_style = lv_obj_style_get_selector_state(obj->styles[i].selector);
if((state_style & state_inv)) continue;
if(lv_style_get_prop(obj_style->style, LV_STYLE_BLUR_RADIUS, &v)) {
/*Truncate the area to the object*/
ext_size = lv_obj_get_ext_draw_size(obj);
lv_area_copy(&obj_coords, &obj->coords);
obj_coords.x1 -= ext_size;
obj_coords.y1 -= ext_size;
obj_coords.x2 += ext_size;
obj_coords.y2 += ext_size;
invalidate_area_core(obj, &obj_coords);
/*No need to check the children as the widget is already invalidated
*which will redraw the children too*/
return LV_OBJ_TREE_WALK_SKIP_CHILDREN;
}
}
/*Check the next child, maybe it's blurred*/
return LV_OBJ_TREE_WALK_NEXT;
}
else {
/*Not on the area of interest, skip it*/
return LV_OBJ_TREE_WALK_SKIP_CHILDREN;
}
}
lv_result_t lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_display_t * disp = lv_obj_get_display(obj);
if(!lv_display_is_invalidation_enabled(disp)) return;
if(!lv_display_is_invalidation_enabled(disp)) return LV_RESULT_INVALID;
lv_area_t area_tmp;
lv_area_copy(&area_tmp, area);
if(!lv_obj_area_is_visible(obj, &area_tmp)) return;
#if LV_DRAW_TRANSFORM_USE_MATRIX
/**
* When using the global matrix, the vertex coordinates of clip_area lose precision after transformation,
* which can be solved by expanding the redrawing area.
*/
lv_area_increase(&area_tmp, 5, 5);
#else
if(obj->spec_attr && obj->spec_attr->layer_type == LV_LAYER_TYPE_TRANSFORM) {
/*Make the area slightly larger to avoid rounding errors.
*5 is an empirical value*/
lv_area_increase(&area_tmp, 5, 5);
}
#endif
lv_result_t res = invalidate_area_core(obj, &area_tmp);
if(res == LV_RESULT_INVALID) return res;
lv_inv_area(lv_obj_get_display(obj), &area_tmp);
/*If this area is on a blurred widget, invalidate that widget too*/
blur_walk_data_t blur_walk_data;
blur_walk_data.requester_obj = obj;
blur_walk_data.inv_area = &area_tmp;
lv_obj_tree_walk(disp->act_scr, blur_walk_cb, &blur_walk_data);
if(disp->prev_scr) lv_obj_tree_walk(disp->prev_scr, blur_walk_cb, &blur_walk_data);
lv_obj_tree_walk(disp->sys_layer, blur_walk_cb, &blur_walk_data);
lv_obj_tree_walk(disp->top_layer, blur_walk_cb, &blur_walk_data);
lv_obj_tree_walk(disp->bottom_layer, blur_walk_cb, &blur_walk_data);
return res;
}
void lv_obj_invalidate(const lv_obj_t * obj)
lv_result_t lv_obj_invalidate(const lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
@@ -901,7 +962,9 @@ void lv_obj_invalidate(const lv_obj_t * obj)
obj_coords.x2 += ext_size;
obj_coords.y2 += ext_size;
lv_obj_invalidate_area(obj, &obj_coords);
lv_result_t res = lv_obj_invalidate_area(obj, &obj_coords);
return res;
}
bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area)
@@ -1351,4 +1414,26 @@ static lv_obj_tree_walk_res_t update_layout_completed_cb(lv_obj_t * obj, void *
LV_UNUSED(user_data);
lv_obj_send_event(obj, LV_EVENT_UPDATE_LAYOUT_COMPLETED, NULL);
return LV_OBJ_TREE_WALK_NEXT;
}
}
static lv_result_t invalidate_area_core(const lv_obj_t * obj, lv_area_t * area_tmp)
{
if(!lv_obj_area_is_visible(obj, area_tmp)) return LV_RESULT_INVALID;
#if LV_DRAW_TRANSFORM_USE_MATRIX
/**
* When using the global matrix, the vertex coordinates of clip_area lose precision after transformation,
* which can be solved by expanding the redrawing area.
*/
lv_area_increase(area_tmp, 5, 5);
#else
if(obj->spec_attr && obj->spec_attr->layer_type == LV_LAYER_TYPE_TRANSFORM) {
/*Make the area slightly larger to avoid rounding errors.
*5 is an empirical value*/
lv_area_increase(area_tmp, 5, 5);
}
#endif
lv_result_t res = lv_inv_area(lv_obj_get_display(obj), area_tmp);
return res;
}
+6 -2
View File
@@ -401,14 +401,18 @@ void lv_obj_get_transformed_area(const lv_obj_t * obj, lv_area_t * area, lv_obj_
* The area will be truncated to the object's area and marked for redraw.
* @param obj pointer to an object
* @param area the area to redraw
* @return LV_RESULT_OK: the area is invalidated; LV_RESULT_INVALID: the area wasn't invalidated.
* (maybe it was off-screen or fully clipped)
*/
void lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area);
lv_result_t lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area);
/**
* Mark the object as invalid to redrawn its area
* @param obj pointer to an object
* @return LV_RESULT_OK: the area is invalidated; LV_RESULT_INVALID: the area wasn't invalidated.
* (maybe it was off-screen or fully clipped)
*/
void lv_obj_invalidate(const lv_obj_t * obj);
lv_result_t lv_obj_invalidate(const lv_obj_t * obj);
/**
* Tell whether an area of an object is visible (even partially) now or not
+26 -1
View File
@@ -746,7 +746,8 @@ void lv_obj_set_style_opa_layered(lv_obj_t * obj, lv_opa_t value, lv_style_selec
lv_obj_set_local_style_prop(obj, LV_STYLE_OPA_LAYERED, v, selector);
}
void lv_obj_set_style_color_filter_dsc(lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector)
void lv_obj_set_style_color_filter_dsc(lv_obj_t * obj, const lv_color_filter_dsc_t * value,
lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = value
@@ -778,6 +779,30 @@ void lv_obj_set_style_recolor_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selec
lv_obj_set_local_style_prop(obj, LV_STYLE_RECOLOR_OPA, v, selector);
}
void lv_obj_set_style_blur_radius(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BLUR_RADIUS, v, selector);
}
void lv_obj_set_style_blur_backdrop(lv_obj_t * obj, bool value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BLUR_BACKDROP, v, selector);
}
void lv_obj_set_style_blur_quality(lv_obj_t * obj, lv_blur_quality_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BLUR_QUALITY, v, selector);
}
void lv_obj_set_style_anim(lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector)
{
lv_style_value_t v = {
+37 -8
View File
@@ -243,7 +243,8 @@ static inline lv_color_t lv_obj_get_style_bg_grad_color(const lv_obj_t * obj, lv
static inline lv_color_t lv_obj_get_style_bg_grad_color_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR));
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_BG_GRAD_COLOR));
return v.color;
}
@@ -303,7 +304,8 @@ static inline lv_color_t lv_obj_get_style_bg_image_recolor(const lv_obj_t * obj,
static inline lv_color_t lv_obj_get_style_bg_image_recolor_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMAGE_RECOLOR));
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_BG_IMAGE_RECOLOR));
return v.color;
}
@@ -327,7 +329,8 @@ static inline lv_color_t lv_obj_get_style_border_color(const lv_obj_t * obj, lv_
static inline lv_color_t lv_obj_get_style_border_color_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR));
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_BORDER_COLOR));
return v.color;
}
@@ -369,7 +372,8 @@ static inline lv_color_t lv_obj_get_style_outline_color(const lv_obj_t * obj, lv
static inline lv_color_t lv_obj_get_style_outline_color_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR));
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_OUTLINE_COLOR));
return v.color;
}
@@ -417,7 +421,8 @@ static inline lv_color_t lv_obj_get_style_shadow_color(const lv_obj_t * obj, lv_
static inline lv_color_t lv_obj_get_style_shadow_color_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR));
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_SHADOW_COLOR));
return v.color;
}
@@ -441,7 +446,8 @@ static inline lv_color_t lv_obj_get_style_image_recolor(const lv_obj_t * obj, lv
static inline lv_color_t lv_obj_get_style_image_recolor_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_IMAGE_RECOLOR));
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_IMAGE_RECOLOR));
return v.color;
}
@@ -591,7 +597,8 @@ static inline lv_color_t lv_obj_get_style_text_outline_stroke_color(const lv_obj
static inline lv_color_t lv_obj_get_style_text_outline_stroke_color_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_OUTLINE_STROKE_COLOR));
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_TEXT_OUTLINE_STROKE_COLOR));
return v.color;
}
@@ -661,6 +668,24 @@ static inline lv_opa_t lv_obj_get_style_recolor_opa(const lv_obj_t * obj, lv_par
return (lv_opa_t)v.num;
}
static inline int32_t lv_obj_get_style_blur_radius(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BLUR_RADIUS);
return (int32_t)v.num;
}
static inline bool lv_obj_get_style_blur_backdrop(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BLUR_BACKDROP);
return (bool)v.num;
}
static inline lv_blur_quality_t lv_obj_get_style_blur_quality(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BLUR_QUALITY);
return (lv_blur_quality_t)v.num;
}
static inline const lv_anim_t * lv_obj_get_style_anim(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM);
@@ -897,10 +922,14 @@ void lv_obj_set_style_radial_offset(lv_obj_t * obj, int32_t value, lv_style_sele
void lv_obj_set_style_clip_corner(lv_obj_t * obj, bool value, lv_style_selector_t selector);
void lv_obj_set_style_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_opa_layered(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_color_filter_dsc(lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector);
void lv_obj_set_style_color_filter_dsc(lv_obj_t * obj, const lv_color_filter_dsc_t * value,
lv_style_selector_t selector);
void lv_obj_set_style_color_filter_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_recolor(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_recolor_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_blur_radius(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_blur_backdrop(lv_obj_t * obj, bool value, lv_style_selector_t selector);
void lv_obj_set_style_blur_quality(lv_obj_t * obj, lv_blur_quality_t value, lv_style_selector_t selector);
void lv_obj_set_style_anim(lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector);
void lv_obj_set_style_anim_duration(lv_obj_t * obj, uint32_t value, lv_style_selector_t selector);
void lv_obj_set_style_transition(lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector);
+10 -8
View File
@@ -266,11 +266,11 @@ void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj)
LV_PROFILER_REFR_END;
}
void lv_inv_area(lv_display_t * disp, const lv_area_t * area_p)
lv_result_t lv_inv_area(lv_display_t * disp, const lv_area_t * area_p)
{
if(!disp) disp = lv_display_get_default();
if(!disp) return;
if(!lv_display_is_invalidation_enabled(disp)) return;
if(!disp) return LV_RESULT_INVALID;
if(!lv_display_is_invalidation_enabled(disp)) return LV_RESULT_INVALID;
/**
* There are two reasons for this issue:
@@ -288,7 +288,7 @@ void lv_inv_area(lv_display_t * disp, const lv_area_t * area_p)
/*Clear the invalidate buffer if the parameter is NULL*/
if(area_p == NULL) {
disp->inv_p = 0;
return;
return LV_RESULT_OK;
}
lv_area_t scr_area;
@@ -301,7 +301,7 @@ void lv_inv_area(lv_display_t * disp, const lv_area_t * area_p)
bool suc;
suc = lv_area_intersect(&com_area, area_p, &scr_area);
if(suc == false) return; /*Out of the screen*/
if(suc == false) return LV_RESULT_INVALID; /*Out of the screen*/
if(disp->color_format == LV_COLOR_FORMAT_I1) {
/*Make sure that the X coordinates start and end on byte boundary.
@@ -315,16 +315,16 @@ void lv_inv_area(lv_display_t * disp, const lv_area_t * area_p)
disp->inv_areas[0] = scr_area;
disp->inv_p = 1;
lv_display_send_event(disp, LV_EVENT_REFR_REQUEST, NULL);
return;
return LV_RESULT_OK;
}
lv_result_t res = lv_display_send_event(disp, LV_EVENT_INVALIDATE_AREA, &com_area);
if(res != LV_RESULT_OK) return;
if(res != LV_RESULT_OK) return LV_RESULT_INVALID;
/*Save only if this area is not in one of the saved areas*/
uint16_t i;
for(i = 0; i < disp->inv_p; i++) {
if(lv_area_is_in(&com_area, &disp->inv_areas[i], 0) != false) return;
if(lv_area_is_in(&com_area, &disp->inv_areas[i], 0) != false) return LV_RESULT_OK;
}
/*Save the area*/
@@ -337,6 +337,8 @@ void lv_inv_area(lv_display_t * disp, const lv_area_t * area_p)
disp->inv_p++;
lv_display_send_event(disp, LV_EVENT_REFR_REQUEST, NULL);
return LV_RESULT_OK;
}
/**
+2 -1
View File
@@ -43,8 +43,9 @@ void lv_refr_deinit(void);
* @param area_p pointer to area which should be invalidated (NULL: delete the invalidated areas)
* @param disp pointer to display where the area should be invalidated (NULL can be used if there is
* only one display)
* @return LV_RESULT_OK: the area is invalidated; LV_RESULT_INVALID: the area wasn't invalidated.
*/
void lv_inv_area(lv_display_t * disp, const lv_area_t * area_p);
lv_result_t lv_inv_area(lv_display_t * disp, const lv_area_t * area_p);
/**
* Get the display which is being refreshed
+2
View File
@@ -605,6 +605,8 @@ static inline size_t get_draw_dsc_size(lv_draw_task_type_t type)
return sizeof(lv_draw_arc_dsc_t);
case LV_DRAW_TASK_TYPE_TRIANGLE:
return sizeof(lv_draw_triangle_dsc_t);
case LV_DRAW_TASK_TYPE_BLUR:
return sizeof(lv_draw_blur_dsc_t);
case LV_DRAW_TASK_TYPE_MASK_RECTANGLE:
return sizeof(lv_draw_mask_rect_dsc_t);
+1
View File
@@ -58,6 +58,7 @@ typedef enum {
LV_DRAW_TASK_TYPE_TRIANGLE,
LV_DRAW_TASK_TYPE_MASK_RECTANGLE,
LV_DRAW_TASK_TYPE_MASK_BITMAP,
LV_DRAW_TASK_TYPE_BLUR,
#if LV_USE_VECTOR_GRAPHIC
LV_DRAW_TASK_TYPE_VECTOR,
#endif
+65
View File
@@ -0,0 +1,65 @@
/**
* @file lv_draw_blur.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_private.h"
#include "lv_draw_blur.h"
#include "../misc/lv_types.h"
#include "../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void LV_ATTRIBUTE_FAST_MEM lv_draw_blur_dsc_init(lv_draw_blur_dsc_t * dsc)
{
lv_memzero(dsc, sizeof(lv_draw_blur_dsc_t));
dsc->base.dsc_size = sizeof(lv_draw_blur_dsc_t);
}
lv_draw_blur_dsc_t * lv_draw_task_get_blur_dsc(lv_draw_task_t * task)
{
return task->type == LV_DRAW_TASK_TYPE_BLUR ? (lv_draw_blur_dsc_t *)task->draw_dsc : NULL;
}
void LV_ATTRIBUTE_FAST_MEM lv_draw_blur(lv_layer_t * layer, const lv_draw_blur_dsc_t * dsc, const lv_area_t * coords)
{
if(dsc->blur_radius <= 0) return;
LV_PROFILER_DRAW_BEGIN;
lv_draw_task_t * t = lv_draw_add_task(layer, coords, LV_DRAW_TASK_TYPE_BLUR);
lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc));
lv_draw_finalize_task_creation(layer, t);
LV_PROFILER_DRAW_END;
}
/**********************
* STATIC FUNCTIONS
**********************/
+82
View File
@@ -0,0 +1,82 @@
/**
* @file lv_draw_blur.h
*
*/
#ifndef LV_DRAW_BLUR_H
#define LV_DRAW_BLUR_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#include "../misc/lv_color.h"
#include "../misc/lv_area.h"
#include "../misc/lv_style.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_draw_dsc_base_t base;
/**
* The intensity of blur.
*/
int32_t blur_radius;
/**
* The corner radius of the blurred area
*/
int32_t corner_radius;
/**
* Sets whether to prefer speed or precision
*/
lv_blur_quality_t quality;
} lv_draw_blur_dsc_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize a blur draw descriptor
* @param dsc pointer to a draw descriptor
*/
void lv_draw_blur_dsc_init(lv_draw_blur_dsc_t * dsc);
/**
* Try to get a blur draw descriptor from a draw task.
* @param task draw task
* @return the task's draw descriptor or NULL if the task is not of type LV_DRAW_TASK_TYPE_BLUR
*/
lv_draw_blur_dsc_t * lv_draw_task_get_blur_dsc(lv_draw_task_t * task);
/**
* Create a blur draw task
* @param layer pointer to a layer
* @param dsc pointer to an initialized `lv_draw_blur_dsc_t` variable
* @param coords coordinates of the character
*/
void lv_draw_blur(lv_layer_t * layer, const lv_draw_blur_dsc_t * dsc, const lv_area_t * coords);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_BLUR_H*/
+3
View File
@@ -409,6 +409,9 @@ static void execute_drawing(lv_draw_task_t * t)
case LV_DRAW_TASK_TYPE_LINE:
lv_draw_sw_line(t, t->draw_dsc);
break;
case LV_DRAW_TASK_TYPE_BLUR:
lv_draw_sw_blur(t, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_TRIANGLE:
lv_draw_sw_triangle(t, t->draw_dsc);
break;
+10
View File
@@ -26,6 +26,7 @@ extern "C" {
#include "../lv_draw_image.h"
#include "../lv_draw_line.h"
#include "../lv_draw_arc.h"
#include "../lv_draw_blur.h"
#include "lv_draw_sw_utils.h"
#include "blend/lv_draw_sw_blend.h"
@@ -121,6 +122,15 @@ void lv_draw_sw_layer(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc,
*/
void lv_draw_sw_triangle(lv_draw_task_t * t, const lv_draw_triangle_dsc_t * dsc);
/**
* Blur an area with SW render
* @param t pointer to a draw task
* @param dsc the draw descriptor
* @param coords the area to blur
*/
void lv_draw_sw_blur(lv_draw_task_t * t, const lv_draw_blur_dsc_t * dsc, const lv_area_t * coords);
/**
* Mask out a rectangle with radius from a current layer
* @param t pointer to a draw task
+395
View File
@@ -0,0 +1,395 @@
/**
* @file lv_draw_sw_blur.c
*
*/
/*********************
* INCLUDES
*********************/
#include "../../misc/lv_area_private.h"
#include "lv_draw_sw_mask_private.h"
#include "../lv_draw_private.h"
#include "lv_draw_sw.h"
#if LV_USE_DRAW_SW
#include "../../misc/lv_math.h"
#include "../../misc/lv_types.h"
#include "../../core/lv_refr_private.h"
#include "../../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
#define BLUR_INTENSITY_BITS 12
#define BLUR_INTENSITY_MAX (1 << 12)
#define BLUR_INTENSITY_HALF ((1 << 12) / 2)
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void blur_2_bytes_init(uint32_t * sum, lv_color16_t * buf, uint32_t sample_len, int32_t stride);
static inline uint16_t blur_2_bytes(uint32_t * sum, uint16_t px, uint32_t intensity);
static void blur_3_bytes_init(uint32_t * sum, volatile uint8_t * buf, uint32_t sample_len, int32_t stride);
static inline void blur_3_bytes(uint32_t * sum, volatile uint8_t * buf, uint32_t intensity);
static int32_t get_rounded_edge_point(int32_t p_start, int32_t p_end, int32_t p, int32_t r);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_sw_blur(lv_draw_task_t * t, const lv_draw_blur_dsc_t * dsc, const lv_area_t * coords)
{
if(dsc->blur_radius == 0) return;
LV_PROFILER_DRAW_BEGIN;
lv_area_t clipped_coords;
if(!lv_area_intersect(&clipped_coords, coords, &t->clip_area)) return;
lv_area_move(&clipped_coords, -t->target_layer->buf_area.x1, -t->target_layer->buf_area.y1);
uint32_t blur_radius = dsc->blur_radius;
/*On larger radius skip some pixels as the result is a blob anyways, so not all pixels matter
*This only every 2nd or 3rd px will be blurred, the result will be stored in the layers buffers,
*and finally the missing pixels are set to nearest blurred pixel. We loose precision but it looks ok
*and and it's very fast.
*/
int32_t skip_cnt = 1;
if(dsc->quality == LV_BLUR_QUALITY_AUTO) {
if(blur_radius >= 32 && dsc->corner_radius == 0) skip_cnt = 3;
else if(blur_radius >= 8) skip_cnt = 2;
}
else if(dsc->quality == LV_BLUR_QUALITY_SPEED) {
if(blur_radius >= 24) skip_cnt = 3;
else skip_cnt = 2;
}
/*The blurring are must be multiples of skip_cnt so the blurring is all directions
* blur the same pixels if some pixels are skipped*/
clipped_coords.x1 = ((clipped_coords.x1 + (skip_cnt - 1)) / skip_cnt) * skip_cnt;
clipped_coords.x2 = ((clipped_coords.x2 - (skip_cnt - 1)) / skip_cnt) * skip_cnt;
clipped_coords.y1 = ((clipped_coords.y1 + (skip_cnt - 1)) / skip_cnt) * skip_cnt;
clipped_coords.y2 = ((clipped_coords.y2 - (skip_cnt - 1)) / skip_cnt) * skip_cnt;
if(lv_area_get_width(&clipped_coords) < 0) return;
if(lv_area_get_height(&clipped_coords) < 0) return;
blur_radius = blur_radius / skip_cnt;
/*We will use an IIR low pass filer in all 4 direction: top to bottom, bottom to top, left to right, right to left.
*Approximate the the filter coefficient from the radius.
*The filter is like: this_px = mix(prev_px, this_px, intensity)
*/
uint32_t intensity = (BLUR_INTENSITY_MAX * blur_radius) / (blur_radius + 4);
int32_t sample_len = LV_MAX(blur_radius / 2, 1);
int32_t radius = dsc->corner_radius;
int32_t w = lv_area_get_width(coords);
int32_t h = lv_area_get_height(coords);
int32_t short_side = LV_MIN(w, h);
if(radius > short_side >> 1) radius = short_side >> 1;
uint32_t px_size = lv_color_format_get_size(t->target_layer->draw_buf->header.cf);
int32_t stride_byte = t->target_layer->draw_buf->header.stride;
int32_t stride_px = stride_byte / px_size;
int32_t next_px_ofs_byte = px_size * skip_cnt;
uint32_t sum[3];
int32_t y;
int32_t x;
/*Blur each column top to bottom and bottom to top.*/
for(x = clipped_coords.x1; x <= clipped_coords.x2; x += skip_cnt) {
int32_t cir_y = get_rounded_edge_point(coords->x1, coords->x2, x, radius);
int32_t y_start = LV_CLAMP(clipped_coords.y1, coords->y1 + cir_y, clipped_coords.y2);
int32_t y_end = LV_CLAMP(clipped_coords.y1, coords->y2 - cir_y, clipped_coords.y2);
/*Make sure that the width and height is a multiple of skip_cnt so that back and forth blurring
*surely affects the same pixels */
y_start = (y_start / skip_cnt) * skip_cnt;
y_end = (y_end / skip_cnt) * skip_cnt;
if(y_start > y_end) continue;
uint32_t sample_len_limited = LV_MIN((y_end - y_start) / skip_cnt + 1, sample_len);
if(px_size >= 3) {
/*Compiler optimization might mishandle it, so add volatile*/
volatile uint8_t * buf_column = lv_draw_buf_goto_xy(t->target_layer->draw_buf, x, y_start);
blur_3_bytes_init(sum, buf_column, sample_len_limited, stride_byte * skip_cnt);
for(y = y_start; y <= y_end; y += skip_cnt) {
blur_3_bytes(sum, buf_column, intensity);
buf_column += stride_byte * skip_cnt;
}
buf_column = lv_draw_buf_goto_xy(t->target_layer->draw_buf, x, y_end);
blur_3_bytes_init(sum, buf_column, sample_len_limited, -stride_byte * skip_cnt);
for(y = y_start; y <= y_end; y += skip_cnt) {
blur_3_bytes(sum, buf_column, intensity);
buf_column -= stride_byte * skip_cnt;
}
}
else if(px_size == 2) {
uint16_t * buf16_column = lv_draw_buf_goto_xy(t->target_layer->draw_buf, x, y_start);
blur_2_bytes_init(sum, (lv_color16_t *)buf16_column, sample_len_limited, stride_px * skip_cnt);
uint16_t buf16_prev = buf16_column[0] + 1; /*Make sure that it's not equal in the first round*/
for(y = y_start; y <= y_end; y += skip_cnt) {
if(buf16_prev != *buf16_column) {
*buf16_column = blur_2_bytes(sum, *buf16_column, intensity);
buf16_prev = *buf16_column;
}
buf16_column += stride_px * skip_cnt;
}
buf16_column = lv_draw_buf_goto_xy(t->target_layer->draw_buf, x, y_end);
blur_2_bytes_init(sum, (lv_color16_t *)buf16_column, sample_len_limited, -stride_px * skip_cnt);
buf16_prev = buf16_column[0] + 1; /*Make sure that it's not equal in the first round*/
for(y = y_start; y <= y_end; y += skip_cnt) {
if(buf16_prev != *buf16_column) {
*buf16_column = blur_2_bytes(sum, *buf16_column, intensity);
buf16_prev = *buf16_column;
}
buf16_column -= stride_px * skip_cnt;
}
}
}
/*Blur each line from left to right and right to left.
*Also fill the gap in each line because of skipped pixels*/
for(y = clipped_coords.y1; y <= clipped_coords.y2; y += skip_cnt) {
int32_t cir_x = get_rounded_edge_point(coords->y1, coords->y2, y, radius);
int32_t x_start = LV_CLAMP(clipped_coords.x1, coords->x1 + cir_x, clipped_coords.x2);
int32_t x_end = LV_CLAMP(clipped_coords.x1, coords->x2 - cir_x, clipped_coords.x2);
/*Make sure that the width and height is a multiple of skip_cnt so that back and forth blurring
*surely affects the same pixels */
x_start = (x_start / skip_cnt) * skip_cnt;
x_end = (x_end / skip_cnt) * skip_cnt;
if(x_start > x_end) continue;
uint32_t line_len_byte = (x_end - x_start + skip_cnt) * px_size;
uint32_t sample_len_limited = LV_MIN((x_end - x_start) / skip_cnt + 1, sample_len);
if(px_size >= 3) {
/*Compiler optimization might mishandle it, so add volatile*/
volatile uint8_t * buf_line = lv_draw_buf_goto_xy(t->target_layer->draw_buf, x_start, y);
blur_3_bytes_init(sum, buf_line, sample_len_limited, px_size * skip_cnt);
buf_line += px_size * skip_cnt;
for(x = x_start + skip_cnt; x <= x_end; x += skip_cnt) {
blur_3_bytes(sum, buf_line, intensity);
buf_line += next_px_ofs_byte;
}
buf_line = lv_draw_buf_goto_xy(t->target_layer->draw_buf, x_end, y);
blur_3_bytes_init(sum, buf_line, sample_len_limited, - px_size * skip_cnt);
for(x = x_start; x <= x_end; x += skip_cnt) {
blur_3_bytes(sum, buf_line, intensity);
/*This is the final pixel, fill the gaps in the line by just repeating the pixel (simple upscale)*/
if(skip_cnt == 2) {
buf_line[px_size + 0] = buf_line[0];
buf_line[px_size + 1] = buf_line[1];
buf_line[px_size + 2] = buf_line[2];
}
else if(skip_cnt == 3) {
buf_line[px_size + 0] = buf_line[0];
buf_line[px_size + 1] = buf_line[1];
buf_line[px_size + 2] = buf_line[2];
buf_line[px_size * 2 + 0] = buf_line[0];
buf_line[px_size * 2 + 1] = buf_line[1];
buf_line[px_size * 2 + 2] = buf_line[2];
}
/*Fill the empty lines by duplicating a the finished filled lines to the gaps*/
if(skip_cnt > 1 && x + skip_cnt > x_end) {
uint8_t * buf_copy_from = lv_draw_buf_goto_xy(t->target_layer->draw_buf, x_start, y);
lv_memcpy(buf_copy_from + stride_byte, buf_copy_from, line_len_byte);
if(skip_cnt == 3) {
lv_memcpy(buf_copy_from + stride_byte * 2, buf_copy_from, line_len_byte);
}
}
buf_line -= next_px_ofs_byte;
}
}
else if(px_size == 2) {
uint16_t * buf16_line = lv_draw_buf_goto_xy(t->target_layer->draw_buf, x_start, y);
blur_2_bytes_init(sum, (lv_color16_t *)buf16_line, sample_len_limited, skip_cnt);
uint16_t buf16_prev = buf16_line[0] + 1; /*Make sure that it's not equal in the first round*/
for(x = x_start; x <= x_end; x += skip_cnt) {
if(buf16_prev != *buf16_line) {
*buf16_line = blur_2_bytes(sum, *buf16_line, intensity);
buf16_prev = *buf16_line;
}
buf16_line += skip_cnt;
}
buf16_line = lv_draw_buf_goto_xy(t->target_layer->draw_buf, x_end, y);
blur_2_bytes_init(sum, (lv_color16_t *)buf16_line, sample_len_limited, - skip_cnt);
buf16_prev = buf16_line[0] + 1; /*Make sure that it's not equal in the first round*/
for(x = x_start; x <= x_end; x += skip_cnt) {
if(buf16_prev != *buf16_line) {
*buf16_line = blur_2_bytes(sum, *buf16_line, intensity);
buf16_prev = *buf16_line;
}
/*This is the final pixel, fill the gaps in the line by just repeating the pixel (simple upscale)*/
if(skip_cnt == 2) {
/*Fill the empty lines by duplicating a the finished filled lines to the gaps*/
buf16_line[1] = buf16_line[0];
}
else if(skip_cnt == 3) {
/*Fill the empty lines by duplicating a the finished filled lines to the gaps*/
buf16_line[1] = buf16_line[0];
buf16_line[2] = buf16_line[0];
}
/*Fill the empty lines by duplicating a the finished filled lines to the gaps*/
if(skip_cnt > 1 && x + skip_cnt > x_end) {
uint8_t * buf_copy_from = lv_draw_buf_goto_xy(t->target_layer->draw_buf, x_start, y);
lv_memcpy(buf_copy_from + stride_byte, buf_copy_from, line_len_byte);
if(skip_cnt == 3) {
lv_memcpy(buf_copy_from + stride_byte * 2, buf_copy_from, line_len_byte);
}
}
buf16_line -= skip_cnt;
}
}
}
LV_PROFILER_DRAW_END;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void blur_3_bytes_init(uint32_t * sum, volatile uint8_t * buf, uint32_t sample_len, int32_t stride)
{
uint32_t s;
sum[0] = 0;
sum[1] = 0;
sum[2] = 0;
for(s = 0; s < sample_len; s++) {
sum[0] += buf[0];
sum[1] += buf[1];
sum[2] += buf[2];
buf += stride;
}
sum[0] = (sum[0] << BLUR_INTENSITY_BITS) / sample_len;
sum[1] = (sum[1] << BLUR_INTENSITY_BITS) / sample_len;
sum[2] = (sum[2] << BLUR_INTENSITY_BITS) / sample_len;
}
static void blur_2_bytes_init(uint32_t * sum, lv_color16_t * buf, uint32_t sample_len, int32_t stride)
{
uint32_t s;
sum[0] = 0;
sum[1] = 0;
sum[2] = 0;
for(s = 0; s < sample_len; s++) {
sum[0] += buf->red;
sum[1] += buf->green;
sum[2] += buf->blue;
buf += stride;
}
sum[0] = (sum[0] << BLUR_INTENSITY_BITS) / sample_len;
sum[1] = (sum[1] << BLUR_INTENSITY_BITS) / sample_len;
sum[2] = (sum[2] << BLUR_INTENSITY_BITS) / sample_len;
}
static inline uint16_t blur_2_bytes(uint32_t * sum, uint16_t px, uint32_t intensity)
{
const uint32_t inv = BLUR_INTENSITY_MAX - intensity;
const uint32_t half = BLUR_INTENSITY_MAX >> 1;
const uint32_t shift = BLUR_INTENSITY_BITS;
/* unpack */
uint32_t r = px >> 11;
uint32_t g = (px >> 5) & 0x3F;
uint32_t b = px & 0x1F;
uint32_t s0 = sum[0];
uint32_t s1 = sum[1];
uint32_t s2 = sum[2];
/* fused multiply-accumulate pattern */
s0 = (s0 * intensity >> shift) + (r * inv);
s1 = (s1 * intensity >> shift) + (g * inv);
s2 = (s2 * intensity >> shift) + (b * inv);
sum[0] = s0;
sum[1] = s1;
sum[2] = s2;
/* final */
r = (s0 + half) >> shift;
g = (s1 + half) >> shift;
b = (s2 + half) >> shift;
return (uint16_t)((r << 11) | (g << 5) | b);
}
static inline void blur_3_bytes(uint32_t * sum, volatile uint8_t * buf, uint32_t intensity)
{
uint32_t intensity_inv = BLUR_INTENSITY_MAX - intensity;
sum[0] = ((sum[0] * intensity) >> BLUR_INTENSITY_BITS) + ((buf[0] * intensity_inv));
buf[0] = sum[0] >> BLUR_INTENSITY_BITS;
sum[1] = ((sum[1] * intensity) >> BLUR_INTENSITY_BITS) + ((buf[1] * intensity_inv));
buf[1] = sum[1] >> BLUR_INTENSITY_BITS;
sum[2] = ((sum[2] * intensity) >> BLUR_INTENSITY_BITS) + ((buf[2] * intensity_inv));
buf[2] = sum[2] >> BLUR_INTENSITY_BITS;
}
/**
* Get the X or Y point for a rounded edge.
* If the X coordinates are used Y will be returned and vice versa
* Calculates the left or top edge
* @param p_start the edge's X1 or Y1 coordinate
* @param p_end the edge's X2 or Y2 coordinate
* @param p the X or Y coordinate on the edge for which the related X or X should be returned
* @param r the radius of the corner
* @return the X or Y coordinate corresponding to the provided coordinates
*/
static int32_t get_rounded_edge_point(int32_t p_start, int32_t p_end, int32_t p, int32_t r)
{
if(p < p_start + r) p = r - (p - p_start);
else if(p > p_end - r) p = r - (p_end - p);
else return 0;
uint32_t res = lv_sqrt32(r * r - p * p);
return r - res;
}
#endif /*LV_USE_DRAW_SW*/
+11 -1
View File
@@ -118,6 +118,12 @@ typedef enum {
LV_BORDER_SIDE_INTERNAL = 0x10, /**< FOR matrix-like objects (e.g. Button matrix)*/
} lv_border_side_t;
typedef enum {
LV_BLUR_QUALITY_AUTO = 0, /**< Set the quality automatically */
LV_BLUR_QUALITY_SPEED, /**< Prefer speed over precision */
LV_BLUR_QUALITY_PRECISION, /**< Prefer precision over speed*/
} lv_blur_quality_t;
/** A image colorkey definition.
* The transparency within the color range of [low, high] will be set to LV_OPA_TRANSP If the "enable" flag is set to true.
*/
@@ -293,7 +299,11 @@ enum _lv_style_id_t {
LV_STYLE_GRID_CELL_Y_ALIGN = 136,
LV_STYLE_IMAGE_COLORKEY = 137,
LV_STYLE_LAST_BUILT_IN_PROP = 138,
LV_STYLE_BLUR_RADIUS = 138,
LV_STYLE_BLUR_BACKDROP = 139,
LV_STYLE_BLUR_QUALITY = 140,
LV_STYLE_LAST_BUILT_IN_PROP,
LV_STYLE_NUM_BUILT_IN_PROPS = LV_STYLE_LAST_BUILT_IN_PROP + 1,
+24
View File
@@ -778,6 +778,30 @@ void lv_style_set_recolor_opa(lv_style_t * style, lv_opa_t value)
lv_style_set_prop(style, LV_STYLE_RECOLOR_OPA, v);
}
void lv_style_set_blur_radius(lv_style_t * style, int32_t value)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_style_set_prop(style, LV_STYLE_BLUR_RADIUS, v);
}
void lv_style_set_blur_backdrop(lv_style_t * style, bool value)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_style_set_prop(style, LV_STYLE_BLUR_BACKDROP, v);
}
void lv_style_set_blur_quality(lv_style_t * style, lv_blur_quality_t value)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_style_set_prop(style, LV_STYLE_BLUR_QUALITY, v);
}
void lv_style_set_anim(lv_style_t * style, const lv_anim_t * value)
{
lv_style_value_t v = {
+18
View File
@@ -110,6 +110,9 @@ void lv_style_set_color_filter_dsc(lv_style_t * style, const lv_color_filter_dsc
void lv_style_set_color_filter_opa(lv_style_t * style, lv_opa_t value);
void lv_style_set_recolor(lv_style_t * style, lv_color_t value);
void lv_style_set_recolor_opa(lv_style_t * style, lv_opa_t value);
void lv_style_set_blur_radius(lv_style_t * style, int32_t value);
void lv_style_set_blur_backdrop(lv_style_t * style, bool value);
void lv_style_set_blur_quality(lv_style_t * style, lv_blur_quality_t value);
void lv_style_set_anim(lv_style_t * style, const lv_anim_t * value);
void lv_style_set_anim_duration(lv_style_t * style, uint32_t value);
void lv_style_set_transition(lv_style_t * style, const lv_style_transition_dsc_t * value);
@@ -620,6 +623,21 @@ void lv_style_set_grid_cell_row_span(lv_style_t * style, int32_t value);
.prop = LV_STYLE_RECOLOR_OPA, .value = { .num = (int32_t)val } \
}
#define LV_STYLE_CONST_BLUR_RADIUS(val) \
{ \
.prop = LV_STYLE_BLUR_RADIUS, .value = { .num = (int32_t)val } \
}
#define LV_STYLE_CONST_BLUR_BACKDROP(val) \
{ \
.prop = LV_STYLE_BLUR_BACKDROP, .value = { .num = (int32_t)val } \
}
#define LV_STYLE_CONST_BLUR_QUALITY(val) \
{ \
.prop = LV_STYLE_BLUR_QUALITY, .value = { .num = (int32_t)val } \
}
#define LV_STYLE_CONST_ANIM(val) \
{ \
.prop = LV_STYLE_ANIM, .value = { .ptr = val } \
+3 -4
View File
@@ -978,7 +978,6 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj)
}
else if(lv_obj_check_type(obj, &lv_dropdownlist_class)) {
lv_obj_add_style(obj, &theme->styles.card, 0);
lv_obj_add_style(obj, &theme->styles.clip_corner, 0);
lv_obj_add_style(obj, &theme->styles.line_space_large, 0);
lv_obj_add_style(obj, &theme->styles.dropdown_list, 0);
lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR);
@@ -1133,18 +1132,18 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj)
return;
}
else if(lv_obj_check_type(obj, &lv_msgbox_header_class)) {
lv_obj_add_style(obj, &theme->styles.pad_tiny, 0);
lv_obj_add_style(obj, &theme->styles.pad_small, 0);
lv_obj_add_style(obj, &theme->styles.bg_color_grey, 0);
return;
}
else if(lv_obj_check_type(obj, &lv_msgbox_footer_class)) {
lv_obj_add_style(obj, &theme->styles.pad_tiny, 0);
lv_obj_add_style(obj, &theme->styles.pad_small, 0);
return;
}
else if(lv_obj_check_type(obj, &lv_msgbox_content_class)) {
lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR);
lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED);
lv_obj_add_style(obj, &theme->styles.pad_tiny, 0);
lv_obj_add_style(obj, &theme->styles.pad_small, 0);
return;
}
else if(lv_obj_check_type(obj, &lv_msgbox_header_button_class) ||
+17 -6
View File
@@ -509,10 +509,18 @@ static void draw_indic(lv_event_t * e)
draw_rect_dsc.base.layer = layer;
lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &draw_rect_dsc);
int32_t bg_radius = lv_obj_get_style_radius(obj, LV_PART_MAIN);
int32_t short_side = LV_MIN(barw, barh);
if(bg_radius > short_side >> 1) bg_radius = short_side >> 1;
bool backdrop_blur = lv_obj_get_style_blur_backdrop(obj, LV_PART_INDICATOR);
lv_draw_blur_dsc_t draw_blur_dsc;
lv_draw_blur_dsc_init(&draw_blur_dsc);
draw_blur_dsc.corner_radius = draw_rect_dsc.radius;
lv_obj_init_draw_blur_dsc(obj, LV_PART_INDICATOR, &draw_blur_dsc);
if(backdrop_blur) lv_draw_blur(layer, &draw_blur_dsc, &indic_area);
int32_t indic_radius = draw_rect_dsc.radius;
short_side = LV_MIN(lv_area_get_width(&bar->indic_area), lv_area_get_height(&bar->indic_area));
if(indic_radius > short_side >> 1) indic_radius = short_side >> 1;
@@ -556,12 +564,12 @@ static void draw_indic(lv_event_t * e)
if(radius_issue || mask_needed) {
if(!radius_issue) {
/*Draw only the shadow*/
lv_draw_rect_dsc_t draw_tmp_dsc = draw_rect_dsc;
draw_tmp_dsc.border_opa = 0;
draw_tmp_dsc.outline_opa = 0;
draw_tmp_dsc.bg_opa = 0;
draw_tmp_dsc.bg_image_opa = 0;
lv_draw_rect(layer, &draw_tmp_dsc, &indic_area);
lv_draw_rect_dsc_t draw_rect_tmp_dsc = draw_rect_dsc;
draw_rect_tmp_dsc.border_opa = 0;
draw_rect_tmp_dsc.outline_opa = 0;
draw_rect_tmp_dsc.bg_opa = 0;
draw_rect_tmp_dsc.bg_image_opa = 0;
lv_draw_rect(layer, &draw_rect_tmp_dsc, &indic_area);
}
else {
draw_rect_dsc.border_opa = 0;
@@ -617,10 +625,13 @@ static void draw_indic(lv_event_t * e)
draw_tmp_dsc.bg_opa = 0;
draw_tmp_dsc.bg_image_opa = 0;
lv_draw_rect(layer, &draw_tmp_dsc, &indic_area);
}
else {
lv_draw_rect(layer, &draw_rect_dsc, &indic_area);
}
if(!backdrop_blur) lv_draw_blur(layer, &draw_blur_dsc, &indic_area);
}
static void lv_bar_event(const lv_obj_class_t * class_p, lv_event_t * e)
+1 -1
View File
@@ -18,7 +18,7 @@
extern const lv_property_name_t lv_obj_property_names[75];
extern const lv_property_name_t lv_roller_property_names[3];
extern const lv_property_name_t lv_slider_property_names[8];
extern const lv_property_name_t lv_style_property_names[121];
extern const lv_property_name_t lv_style_property_names[123];
extern const lv_property_name_t lv_textarea_property_names[15];
#endif
#endif
+4 -2
View File
@@ -14,7 +14,7 @@
* Generated code from properties.py
*/
/* *INDENT-OFF* */
const lv_property_name_t lv_style_property_names[121] = {
const lv_property_name_t lv_style_property_names[123] = {
{"align", LV_PROPERTY_STYLE_ALIGN,},
{"anim", LV_PROPERTY_STYLE_ANIM,},
{"anim_duration", LV_PROPERTY_STYLE_ANIM_DURATION,},
@@ -40,6 +40,9 @@ const lv_property_name_t lv_style_property_names[121] = {
{"bg_opa", LV_PROPERTY_STYLE_BG_OPA,},
{"bitmap_mask_src", LV_PROPERTY_STYLE_BITMAP_MASK_SRC,},
{"blend_mode", LV_PROPERTY_STYLE_BLEND_MODE,},
{"blur_backdrop", LV_PROPERTY_STYLE_BLUR_BACKDROP,},
{"blur_quality", LV_PROPERTY_STYLE_BLUR_QUALITY,},
{"blur_radius", LV_PROPERTY_STYLE_BLUR_RADIUS,},
{"border_color", LV_PROPERTY_STYLE_BORDER_COLOR,},
{"border_opa", LV_PROPERTY_STYLE_BORDER_OPA,},
{"border_post", LV_PROPERTY_STYLE_BORDER_POST,},
@@ -68,7 +71,6 @@ const lv_property_name_t lv_style_property_names[121] = {
{"image_opa", LV_PROPERTY_STYLE_IMAGE_OPA,},
{"image_recolor", LV_PROPERTY_STYLE_IMAGE_RECOLOR,},
{"image_recolor_opa", LV_PROPERTY_STYLE_IMAGE_RECOLOR_OPA,},
{"last_built_in_prop", LV_PROPERTY_STYLE_LAST_BUILT_IN_PROP,},
{"layout", LV_PROPERTY_STYLE_LAYOUT,},
{"length", LV_PROPERTY_STYLE_LENGTH,},
{"line_color", LV_PROPERTY_STYLE_LINE_COLOR,},
+3 -1
View File
@@ -37,6 +37,9 @@ enum _lv_property_style_id_t {
LV_PROPERTY_ID(STYLE, BG_OPA, LV_PROPERTY_TYPE_INT, LV_STYLE_BG_OPA),
LV_PROPERTY_ID(STYLE, BITMAP_MASK_SRC, LV_PROPERTY_TYPE_POINTER, LV_STYLE_BITMAP_MASK_SRC),
LV_PROPERTY_ID(STYLE, BLEND_MODE, LV_PROPERTY_TYPE_INT, LV_STYLE_BLEND_MODE),
LV_PROPERTY_ID(STYLE, BLUR_BACKDROP, LV_PROPERTY_TYPE_INT, LV_STYLE_BLUR_BACKDROP),
LV_PROPERTY_ID(STYLE, BLUR_QUALITY, LV_PROPERTY_TYPE_INT, LV_STYLE_BLUR_QUALITY),
LV_PROPERTY_ID(STYLE, BLUR_RADIUS, LV_PROPERTY_TYPE_INT, LV_STYLE_BLUR_RADIUS),
LV_PROPERTY_ID(STYLE, BORDER_COLOR, LV_PROPERTY_TYPE_COLOR, LV_STYLE_BORDER_COLOR),
LV_PROPERTY_ID(STYLE, BORDER_OPA, LV_PROPERTY_TYPE_INT, LV_STYLE_BORDER_OPA),
LV_PROPERTY_ID(STYLE, BORDER_POST, LV_PROPERTY_TYPE_INT, LV_STYLE_BORDER_POST),
@@ -65,7 +68,6 @@ enum _lv_property_style_id_t {
LV_PROPERTY_ID(STYLE, IMAGE_OPA, LV_PROPERTY_TYPE_INT, LV_STYLE_IMAGE_OPA),
LV_PROPERTY_ID(STYLE, IMAGE_RECOLOR, LV_PROPERTY_TYPE_COLOR, LV_STYLE_IMAGE_RECOLOR),
LV_PROPERTY_ID(STYLE, IMAGE_RECOLOR_OPA, LV_PROPERTY_TYPE_INT, LV_STYLE_IMAGE_RECOLOR_OPA),
LV_PROPERTY_ID(STYLE, LAST_BUILT_IN_PROP, LV_PROPERTY_TYPE_INVALID, LV_STYLE_LAST_BUILT_IN_PROP),
LV_PROPERTY_ID(STYLE, LAYOUT, LV_PROPERTY_TYPE_INT, LV_STYLE_LAYOUT),
LV_PROPERTY_ID(STYLE, LENGTH, LV_PROPERTY_TYPE_INT, LV_STYLE_LENGTH),
LV_PROPERTY_ID(STYLE, LINE_COLOR, LV_PROPERTY_TYPE_COLOR, LV_STYLE_LINE_COLOR),
+10
View File
@@ -238,6 +238,16 @@ lv_blend_mode_t lv_xml_blend_mode_to_enum(const char * txt)
return 0; /*Return 0 in lack of a better option. */
}
lv_blur_quality_t lv_xml_blur_quality_to_enum(const char * txt)
{
if(lv_streq("auto", txt)) return LV_BLUR_QUALITY_AUTO;
if(lv_streq("speed", txt)) return LV_BLUR_QUALITY_SPEED;
if(lv_streq("precision", txt)) return LV_BLUR_QUALITY_PRECISION;
LV_LOG_WARN("%s is an unknown value for blur_quality", txt);
return 0; /*Return 0 in lack of a better option. */
}
lv_event_code_t lv_xml_trigger_text_to_enum_value(const char * txt)
{
if(lv_streq("all", txt)) return LV_EVENT_ALL;
+7
View File
@@ -139,6 +139,13 @@ lv_layout_t lv_xml_layout_to_enum(const char * txt);
*/
lv_blend_mode_t lv_xml_blend_mode_to_enum(const char * txt);
/**
* Convert a blur quality string to enum
* @param txt e.g. "auto"
* @return the related enum, e.g. `LV_BLUR_QUALITY_AUTO`
*/
lv_blur_quality_t lv_xml_blur_quality_to_enum(const char * txt);
/**
* Convert an event trigger string to enum
* @param txt e.g. "clicked"
+4
View File
@@ -267,6 +267,10 @@ lv_result_t lv_xml_register_style(lv_xml_component_scope_t * scope, const char *
else SET_STYLE_IF(recolor, lv_xml_to_color(value));
else SET_STYLE_IF(recolor_opa, lv_xml_to_opa(value));
else SET_STYLE_IF(blur_radius, lv_xml_atoi(value));
else SET_STYLE_IF(blur_backdrop, lv_xml_to_bool(value));
else SET_STYLE_IF(blur_quality, lv_xml_blur_quality_to_enum(value));
else SET_STYLE_IF(layout, lv_xml_layout_to_enum(value));
else SET_STYLE_IF(flex_flow, lv_xml_flex_flow_to_enum(value));
+3
View File
@@ -953,6 +953,9 @@ static void apply_styles(lv_xml_parser_state_t * state, lv_obj_t * obj, const ch
else SET_STYLE_IF(rotary_sensitivity, lv_xml_atoi(value));
else SET_STYLE_IF(recolor, lv_xml_to_color(value));
else SET_STYLE_IF(recolor_opa, lv_xml_to_opa(value));
else SET_STYLE_IF(blur_radius, lv_xml_atoi(value));
else SET_STYLE_IF(blur_backdrop, lv_xml_to_bool(value));
else SET_STYLE_IF(blur_quality, lv_xml_blur_quality_to_enum(value));
else SET_STYLE_IF(layout, lv_xml_layout_to_enum(value));
Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Some files were not shown because too many files have changed in this diff Show More