mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-25 18:29:26 +08:00
feat(line): allow defining an array of point in the draw task (#9269)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
af5c3f12f6
commit
d99d2a553e
@@ -584,45 +584,51 @@ static void chart_event_cb(lv_event_t * e)
|
||||
lv_obj_get_coords(obj, &obj_coords);
|
||||
const lv_chart_series_t * ser = lv_chart_get_series_next(obj, NULL);
|
||||
if(base_dsc->id1 == 1) ser = lv_chart_get_series_next(obj, ser);
|
||||
lv_point_precise_t p1;
|
||||
lv_point_precise_t p2;
|
||||
int32_t i;
|
||||
for(i = 0; i < draw_line_dsc->point_cnt - 1; i++) {
|
||||
p1 = draw_line_dsc->points[i];
|
||||
p2 = draw_line_dsc->points[i + 1];
|
||||
lv_draw_triangle_dsc_t tri_dsc;
|
||||
lv_draw_triangle_dsc_init(&tri_dsc);
|
||||
tri_dsc.p[0].x = (int32_t)p1.x;
|
||||
tri_dsc.p[0].y = (int32_t)p1.y;
|
||||
tri_dsc.p[1].x = (int32_t)p2.x;
|
||||
tri_dsc.p[1].y = (int32_t)p2.y;
|
||||
tri_dsc.p[2].x = (int32_t)(p1.y < p2.y ? p1.x : p2.x);
|
||||
tri_dsc.p[2].y = (int32_t)LV_MAX(p1.y, p2.y);
|
||||
tri_dsc.grad.dir = LV_GRAD_DIR_VER;
|
||||
|
||||
lv_draw_triangle_dsc_t tri_dsc;
|
||||
lv_draw_triangle_dsc_init(&tri_dsc);
|
||||
tri_dsc.p[0].x = (int32_t)draw_line_dsc->p1.x;
|
||||
tri_dsc.p[0].y = (int32_t)draw_line_dsc->p1.y;
|
||||
tri_dsc.p[1].x = (int32_t)draw_line_dsc->p2.x;
|
||||
tri_dsc.p[1].y = (int32_t)draw_line_dsc->p2.y;
|
||||
tri_dsc.p[2].x = (int32_t)(draw_line_dsc->p1.y < draw_line_dsc->p2.y ? draw_line_dsc->p1.x : draw_line_dsc->p2.x);
|
||||
tri_dsc.p[2].y = (int32_t)LV_MAX(draw_line_dsc->p1.y, draw_line_dsc->p2.y);
|
||||
tri_dsc.grad.dir = LV_GRAD_DIR_VER;
|
||||
int32_t full_h = lv_obj_get_height(obj);
|
||||
int32_t fract_upper = (int32_t)(LV_MIN(p1.y, p2.y) - obj_coords.y1) * 255 / full_h;
|
||||
int32_t fract_lower = (int32_t)(LV_MAX(p1.y, p2.y) - obj_coords.y1) * 255 / full_h;
|
||||
tri_dsc.grad.stops[0].color = lv_chart_get_series_color(obj, ser);
|
||||
tri_dsc.grad.stops[0].opa = 255 - fract_upper;
|
||||
tri_dsc.grad.stops[0].frac = 0;
|
||||
tri_dsc.grad.stops[1].color = lv_chart_get_series_color(obj, ser);
|
||||
tri_dsc.grad.stops[1].opa = 255 - fract_lower;
|
||||
tri_dsc.grad.stops[1].frac = 255;
|
||||
|
||||
int32_t full_h = lv_obj_get_height(obj);
|
||||
int32_t fract_uppter = (int32_t)(LV_MIN(draw_line_dsc->p1.y, draw_line_dsc->p2.y) - obj_coords.y1) * 255 / full_h;
|
||||
int32_t fract_lower = (int32_t)(LV_MAX(draw_line_dsc->p1.y, draw_line_dsc->p2.y) - obj_coords.y1) * 255 / full_h;
|
||||
tri_dsc.grad.stops[0].color = lv_chart_get_series_color(obj, ser);
|
||||
tri_dsc.grad.stops[0].opa = 255 - fract_uppter;
|
||||
tri_dsc.grad.stops[0].frac = 0;
|
||||
tri_dsc.grad.stops[1].color = lv_chart_get_series_color(obj, ser);
|
||||
tri_dsc.grad.stops[1].opa = 255 - fract_lower;
|
||||
tri_dsc.grad.stops[1].frac = 255;
|
||||
lv_draw_triangle(base_dsc->layer, &tri_dsc);
|
||||
|
||||
lv_draw_triangle(base_dsc->layer, &tri_dsc);
|
||||
lv_draw_rect_dsc_t rect_dsc;
|
||||
lv_draw_rect_dsc_init(&rect_dsc);
|
||||
rect_dsc.bg_grad.dir = LV_GRAD_DIR_VER;
|
||||
rect_dsc.bg_grad.stops[0].color = lv_chart_get_series_color(obj, ser);
|
||||
rect_dsc.bg_grad.stops[0].frac = 0;
|
||||
rect_dsc.bg_grad.stops[0].opa = 255 - fract_lower;
|
||||
rect_dsc.bg_grad.stops[1].color = lv_chart_get_series_color(obj, ser);
|
||||
rect_dsc.bg_grad.stops[1].frac = 255;
|
||||
rect_dsc.bg_grad.stops[1].opa = 0;
|
||||
|
||||
lv_draw_rect_dsc_t rect_dsc;
|
||||
lv_draw_rect_dsc_init(&rect_dsc);
|
||||
rect_dsc.bg_grad.dir = LV_GRAD_DIR_VER;
|
||||
rect_dsc.bg_grad.stops[0].color = lv_chart_get_series_color(obj, ser);
|
||||
rect_dsc.bg_grad.stops[0].frac = 0;
|
||||
rect_dsc.bg_grad.stops[0].opa = 255 - fract_lower;
|
||||
rect_dsc.bg_grad.stops[1].color = lv_chart_get_series_color(obj, ser);
|
||||
rect_dsc.bg_grad.stops[1].frac = 255;
|
||||
rect_dsc.bg_grad.stops[1].opa = 0;
|
||||
|
||||
lv_area_t rect_area;
|
||||
rect_area.x1 = (int32_t)draw_line_dsc->p1.x;
|
||||
rect_area.x2 = (int32_t)draw_line_dsc->p2.x;
|
||||
rect_area.y1 = (int32_t)LV_MAX(draw_line_dsc->p1.y, draw_line_dsc->p2.y);
|
||||
rect_area.y2 = (int32_t)obj_coords.y2;
|
||||
lv_draw_rect(base_dsc->layer, &rect_dsc, &rect_area);
|
||||
lv_area_t rect_area;
|
||||
rect_area.x1 = (int32_t)p1.x;
|
||||
rect_area.x2 = (int32_t)p2.x;
|
||||
rect_area.y1 = (int32_t)LV_MAX(p1.y, p2.y);
|
||||
rect_area.y2 = (int32_t)obj_coords.y2;
|
||||
lv_draw_rect(base_dsc->layer, &rect_dsc, &rect_area);
|
||||
}
|
||||
}
|
||||
|
||||
bool add_value = false;
|
||||
|
||||
@@ -569,8 +569,10 @@ Line Draw Descriptor
|
||||
The :cpp:type:`lv_draw_line_dsc_t` line descriptor defines line rendering with
|
||||
these fields:
|
||||
|
||||
:p1: First point of line (supports floating-point coordinates).
|
||||
:p2: Second point of line (supports floating-point coordinates).
|
||||
:p1: First point of line (supports floating-point coordinates). Ignored if ``points`` are set.
|
||||
:p2: Second point of line (supports floating-point coordinates). Ignored if ``points`` are set.
|
||||
:points: Array of points to draw.
|
||||
:point_cnt: Number of points in ``points``
|
||||
:color: Line color.
|
||||
:width: Line thickness.
|
||||
:opa: Line opacity (0--255).
|
||||
@@ -580,11 +582,17 @@ these fields:
|
||||
:round_end: Rounds the line end.
|
||||
:raw_end: Set to 1 to skip end calculations if they are unnecessary.
|
||||
|
||||
+If a large amount of points needs to be rendered it's recommended to use ``points``
|
||||
instead of ``p1`` and ``p2`` as it avoids creating many draw tasks.
|
||||
|
||||
Functions for line drawing:
|
||||
|
||||
- :cpp:expr:`lv_draw_line_dsc_init(&dsc)` initializes a line descriptor.
|
||||
- :cpp:expr:`lv_draw_line(layer, &dsc)` creates a task to draw a line.
|
||||
- :cpp:expr:`lv_draw_task_get_line_dsc(draw_task)` retrieves line descriptor.
|
||||
- :cpp:expr:`lv_draw_line_iterate(draw_task, dsc, callback)` is a helper function
|
||||
to call a callback which draws a line between two points. This way it doesn't matter if
|
||||
``p1, p2`` or ``points`` were used as it calls the ``callback`` as needed.
|
||||
|
||||
.. lv_example:: widgets/canvas/lv_example_canvas_7
|
||||
:language: c
|
||||
|
||||
@@ -61,47 +61,63 @@ static void add_faded_area(lv_event_t * e)
|
||||
lv_color_t ser_color = lv_chart_get_series_color(obj, ser);
|
||||
|
||||
/*Draw a triangle below the line witch some opacity gradient*/
|
||||
lv_draw_line_dsc_t * draw_line_dsc = (lv_draw_line_dsc_t *)lv_draw_task_get_draw_dsc(draw_task);
|
||||
lv_draw_line_dsc_t * draw_line_dsc = lv_draw_task_get_line_dsc(draw_task);
|
||||
lv_draw_triangle_dsc_t tri_dsc;
|
||||
|
||||
lv_draw_triangle_dsc_init(&tri_dsc);
|
||||
tri_dsc.p[0].x = draw_line_dsc->p1.x;
|
||||
tri_dsc.p[0].y = draw_line_dsc->p1.y;
|
||||
tri_dsc.p[1].x = draw_line_dsc->p2.x;
|
||||
tri_dsc.p[1].y = draw_line_dsc->p2.y;
|
||||
tri_dsc.p[2].x = draw_line_dsc->p1.y < draw_line_dsc->p2.y ? draw_line_dsc->p1.x : draw_line_dsc->p2.x;
|
||||
tri_dsc.p[2].y = LV_MAX(draw_line_dsc->p1.y, draw_line_dsc->p2.y);
|
||||
tri_dsc.grad.dir = LV_GRAD_DIR_VER;
|
||||
|
||||
int32_t full_h = lv_obj_get_height(obj);
|
||||
int32_t fract_uppter = (int32_t)(LV_MIN(draw_line_dsc->p1.y, draw_line_dsc->p2.y) - coords.y1) * 255 / full_h;
|
||||
int32_t fract_lower = (int32_t)(LV_MAX(draw_line_dsc->p1.y, draw_line_dsc->p2.y) - coords.y1) * 255 / full_h;
|
||||
tri_dsc.grad.stops[0].color = ser_color;
|
||||
tri_dsc.grad.stops[0].opa = (lv_opa_t)(255 - fract_uppter);
|
||||
tri_dsc.grad.stops[0].frac = 0;
|
||||
tri_dsc.grad.stops[1].color = ser_color;
|
||||
tri_dsc.grad.stops[1].opa = (lv_opa_t)(255 - fract_lower);
|
||||
tri_dsc.grad.stops[1].frac = 255;
|
||||
lv_point_precise_t p1;
|
||||
lv_point_precise_t p2;
|
||||
int32_t i;
|
||||
for(i = 0; i < draw_line_dsc->point_cnt - 1; i++) {
|
||||
p1 = draw_line_dsc->points[i];
|
||||
p2 = draw_line_dsc->points[i + 1];
|
||||
if(p1.x == LV_DRAW_LINE_POINT_NONE ||
|
||||
p1.y == LV_DRAW_LINE_POINT_NONE) {
|
||||
continue;
|
||||
}
|
||||
if(p2.x == LV_DRAW_LINE_POINT_NONE ||
|
||||
p2.y == LV_DRAW_LINE_POINT_NONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
lv_draw_triangle(base_dsc->layer, &tri_dsc);
|
||||
tri_dsc.p[0].x = p1.x;
|
||||
tri_dsc.p[0].y = p1.y;
|
||||
tri_dsc.p[1].x = p2.x;
|
||||
tri_dsc.p[1].y = p2.y;
|
||||
tri_dsc.p[2].x = p1.y < p2.y ? p1.x : p2.x;
|
||||
tri_dsc.p[2].y = LV_MAX(p1.y, p2.y);
|
||||
tri_dsc.grad.dir = LV_GRAD_DIR_VER;
|
||||
|
||||
/*Draw rectangle below the triangle*/
|
||||
lv_draw_rect_dsc_t rect_dsc;
|
||||
lv_draw_rect_dsc_init(&rect_dsc);
|
||||
rect_dsc.bg_grad.dir = LV_GRAD_DIR_VER;
|
||||
rect_dsc.bg_grad.stops[0].color = ser_color;
|
||||
rect_dsc.bg_grad.stops[0].frac = 0;
|
||||
rect_dsc.bg_grad.stops[0].opa = (lv_opa_t)(255 - fract_lower);
|
||||
rect_dsc.bg_grad.stops[1].color = ser_color;
|
||||
rect_dsc.bg_grad.stops[1].frac = 255;
|
||||
rect_dsc.bg_grad.stops[1].opa = 0;
|
||||
int32_t full_h = lv_obj_get_height(obj);
|
||||
int32_t fract_upper = (int32_t)(LV_MIN(p1.y, p2.y) - coords.y1) * 255 / full_h;
|
||||
int32_t fract_lower = (int32_t)(LV_MAX(p1.y, p2.y) - coords.y1) * 255 / full_h;
|
||||
tri_dsc.grad.stops[0].color = ser_color;
|
||||
tri_dsc.grad.stops[0].opa = (lv_opa_t)(255 - fract_upper);
|
||||
tri_dsc.grad.stops[0].frac = 0;
|
||||
tri_dsc.grad.stops[1].color = ser_color;
|
||||
tri_dsc.grad.stops[1].opa = (lv_opa_t)(255 - fract_lower);
|
||||
tri_dsc.grad.stops[1].frac = 255;
|
||||
|
||||
lv_area_t rect_area;
|
||||
rect_area.x1 = (int32_t)draw_line_dsc->p1.x;
|
||||
rect_area.x2 = (int32_t)draw_line_dsc->p2.x - 1;
|
||||
rect_area.y1 = (int32_t)LV_MAX(draw_line_dsc->p1.y, draw_line_dsc->p2.y);
|
||||
rect_area.y2 = (int32_t)coords.y2;
|
||||
lv_draw_rect(base_dsc->layer, &rect_dsc, &rect_area);
|
||||
lv_draw_triangle(base_dsc->layer, &tri_dsc);
|
||||
|
||||
/*Draw rectangle below the triangle*/
|
||||
lv_draw_rect_dsc_t rect_dsc;
|
||||
lv_draw_rect_dsc_init(&rect_dsc);
|
||||
rect_dsc.bg_grad.dir = LV_GRAD_DIR_VER;
|
||||
rect_dsc.bg_grad.stops[0].color = ser_color;
|
||||
rect_dsc.bg_grad.stops[0].frac = 0;
|
||||
rect_dsc.bg_grad.stops[0].opa = (lv_opa_t)(255 - fract_lower);
|
||||
rect_dsc.bg_grad.stops[1].color = ser_color;
|
||||
rect_dsc.bg_grad.stops[1].frac = 255;
|
||||
rect_dsc.bg_grad.stops[1].opa = 0;
|
||||
|
||||
lv_area_t rect_area;
|
||||
rect_area.x1 = (int32_t)p1.x;
|
||||
rect_area.x2 = (int32_t)p2.x - 1;
|
||||
rect_area.y1 = (int32_t)LV_MAX(p1.y, p2.y);
|
||||
rect_area.y2 = (int32_t)coords.y2;
|
||||
lv_draw_rect(base_dsc->layer, &rect_dsc, &rect_area);
|
||||
}
|
||||
}
|
||||
|
||||
static void hook_division_lines(lv_event_t * e)
|
||||
|
||||
@@ -25,9 +25,6 @@ void lv_example_chart_6(void)
|
||||
lv_obj_set_size(chart, 200, 150);
|
||||
lv_obj_align(chart, LV_ALIGN_CENTER, 0, -10);
|
||||
|
||||
// lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_Y, 10, 5, 6, 5, true, 40);
|
||||
// lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_X, 10, 5, 10, 1, true, 30);
|
||||
|
||||
lv_obj_add_event_cb(chart, value_changed_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
lv_obj_refresh_ext_draw_size(chart);
|
||||
|
||||
@@ -39,8 +36,6 @@ void lv_example_chart_6(void)
|
||||
lv_chart_set_next_value(chart, ser, (int32_t)lv_rand(10, 90));
|
||||
}
|
||||
|
||||
// lv_chart_set_scale_x(chart, 500);
|
||||
|
||||
lv_obj_t * label = lv_label_create(lv_screen_active());
|
||||
lv_label_set_text(label, "Click on a point");
|
||||
lv_obj_align_to(label, chart, LV_ALIGN_OUT_TOP_MID, 0, -5);
|
||||
|
||||
@@ -5,28 +5,29 @@ static void draw_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_draw_task_t * draw_task = lv_event_get_draw_task(e);
|
||||
lv_draw_dsc_base_t * base_dsc = (lv_draw_dsc_base_t *)lv_draw_task_get_draw_dsc(draw_task);
|
||||
if(base_dsc->part == LV_PART_INDICATOR) {
|
||||
lv_obj_t * obj = lv_event_get_target_obj(e);
|
||||
lv_chart_series_t * ser = lv_chart_get_series_next(obj, NULL);
|
||||
lv_draw_rect_dsc_t * rect_draw_dsc = (lv_draw_rect_dsc_t *)lv_draw_task_get_draw_dsc(draw_task);
|
||||
uint32_t cnt = lv_chart_get_point_count(obj);
|
||||
if(base_dsc->part != LV_PART_INDICATOR) return;
|
||||
lv_obj_t * obj = lv_event_get_target_obj(e);
|
||||
lv_chart_series_t * ser = lv_chart_get_series_next(obj, NULL);
|
||||
lv_draw_fill_dsc_t * fill_draw_dsc = lv_draw_task_get_fill_dsc(draw_task);
|
||||
if(fill_draw_dsc == NULL) return;
|
||||
|
||||
/*Make older value more transparent*/
|
||||
rect_draw_dsc->bg_opa = (lv_opa_t)((LV_OPA_COVER * base_dsc->id2) / (cnt - 1));
|
||||
uint32_t cnt = lv_chart_get_point_count(obj);
|
||||
|
||||
/*Make smaller values blue, higher values red*/
|
||||
int32_t * x_array = lv_chart_get_series_x_array(obj, ser);
|
||||
int32_t * y_array = lv_chart_get_series_y_array(obj, ser);
|
||||
/*dsc->id is the tells drawing order, but we need the ID of the point being drawn.*/
|
||||
uint32_t start_point = lv_chart_get_x_start_point(obj, ser);
|
||||
uint32_t p_act = (start_point + base_dsc->id2) % cnt; /*Consider start point to get the index of the array*/
|
||||
lv_opa_t x_opa = (lv_opa_t)((x_array[p_act] * LV_OPA_50) / 200);
|
||||
lv_opa_t y_opa = (lv_opa_t)((y_array[p_act] * LV_OPA_50) / 1000);
|
||||
/*Make older value more transparent*/
|
||||
fill_draw_dsc->opa = (lv_opa_t)((LV_OPA_COVER * base_dsc->id2) / (cnt - 1));
|
||||
|
||||
rect_draw_dsc->bg_color = lv_color_mix(lv_palette_main(LV_PALETTE_RED),
|
||||
lv_palette_main(LV_PALETTE_BLUE),
|
||||
x_opa + y_opa);
|
||||
}
|
||||
/*Make smaller values blue, higher values red*/
|
||||
int32_t * x_array = lv_chart_get_series_x_array(obj, ser);
|
||||
int32_t * y_array = lv_chart_get_series_y_array(obj, ser);
|
||||
/*dsc->id is the tells drawing order, but we need the ID of the point being drawn.*/
|
||||
uint32_t start_point = lv_chart_get_x_start_point(obj, ser);
|
||||
uint32_t p_act = (start_point + base_dsc->id2) % cnt; /*Consider start point to get the index of the array*/
|
||||
lv_opa_t x_opa = (lv_opa_t)((x_array[p_act] * LV_OPA_50) / 200);
|
||||
lv_opa_t y_opa = (lv_opa_t)((y_array[p_act] * LV_OPA_50) / 1000);
|
||||
|
||||
fill_draw_dsc->color = lv_color_mix(lv_palette_main(LV_PALETTE_RED),
|
||||
lv_palette_main(LV_PALETTE_BLUE),
|
||||
x_opa + y_opa);
|
||||
}
|
||||
|
||||
static void add_data(lv_timer_t * timer)
|
||||
|
||||
@@ -129,7 +129,7 @@ static void eve_execute_drawing(lv_draw_eve_unit_t * u)
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_LINE:
|
||||
lv_draw_eve_line(t, t->draw_dsc);
|
||||
lv_draw_line_iterate(t, t->draw_dsc, lv_draw_eve_line);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_BORDER:
|
||||
lv_draw_eve_border(t, t->draw_dsc, &t->area);
|
||||
|
||||
+8
-1
@@ -673,8 +673,15 @@ static inline size_t get_draw_dsc_size(lv_draw_task_type_t type)
|
||||
static void cleanup_task(lv_draw_task_t * t, lv_display_t * disp)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
if(t->type == LV_DRAW_TASK_TYPE_LINE) {
|
||||
lv_draw_line_dsc_t * draw_line_dsc = t->draw_dsc;
|
||||
if(draw_line_dsc->points) {
|
||||
lv_free(draw_line_dsc->points);
|
||||
draw_line_dsc->points = NULL;
|
||||
}
|
||||
}
|
||||
/*If it was layer drawing free the layer too*/
|
||||
if(t->type == LV_DRAW_TASK_TYPE_LAYER) {
|
||||
else if(t->type == LV_DRAW_TASK_TYPE_LAYER) {
|
||||
lv_draw_image_dsc_t * draw_image_dsc = t->draw_dsc;
|
||||
lv_layer_t * layer_drawn = (lv_layer_t *)draw_image_dsc->src;
|
||||
|
||||
|
||||
+80
-5
@@ -58,10 +58,43 @@ void LV_ATTRIBUTE_FAST_MEM lv_draw_line(lv_layer_t * layer, const lv_draw_line_d
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
|
||||
lv_area_t a;
|
||||
a.x1 = (int32_t)LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width;
|
||||
a.x2 = (int32_t)LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width;
|
||||
a.y1 = (int32_t)LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width;
|
||||
a.y2 = (int32_t)LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width;
|
||||
if(dsc->points == NULL) {
|
||||
a.x1 = (int32_t)LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width;
|
||||
a.x2 = (int32_t)LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width;
|
||||
a.y1 = (int32_t)LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width;
|
||||
a.y2 = (int32_t)LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width;
|
||||
}
|
||||
else {
|
||||
if(dsc->point_cnt <= 1) {
|
||||
LV_LOG_INFO("Skip line drawing as point_cnt was 1");
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
|
||||
a.x1 = LV_COORD_MAX;
|
||||
a.y1 = LV_COORD_MAX;
|
||||
a.x2 = LV_COORD_MIN;
|
||||
a.y2 = LV_COORD_MIN;
|
||||
|
||||
int32_t i;
|
||||
for(i = 0; i < dsc->point_cnt; i++) {
|
||||
if(dsc->points[i].x == LV_DRAW_LINE_POINT_NONE ||
|
||||
dsc->points[i].y == LV_DRAW_LINE_POINT_NONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
a.x1 = (int32_t)LV_MIN(a.x1, dsc->points[i].x);
|
||||
a.x2 = (int32_t)LV_MAX(a.x2, dsc->points[i].x);
|
||||
a.y1 = (int32_t)LV_MIN(a.y1, dsc->points[i].y);
|
||||
a.y2 = (int32_t)LV_MAX(a.y2, dsc->points[i].y);
|
||||
}
|
||||
|
||||
if(a.x1 == LV_COORD_MAX) {
|
||||
LV_LOG_INFO("No valid point was found. Not adding the draw task.");
|
||||
return;
|
||||
}
|
||||
lv_area_increase(&a, dsc->width, dsc->width);
|
||||
}
|
||||
|
||||
if(dsc->base.drop_shadow_opa) {
|
||||
lv_layer_t * ds_layer = lv_draw_layer_create_drop_shadow(layer, &dsc->base, &a);
|
||||
@@ -73,13 +106,55 @@ void LV_ATTRIBUTE_FAST_MEM lv_draw_line(lv_layer_t * layer, const lv_draw_line_d
|
||||
}
|
||||
|
||||
lv_draw_task_t * t = lv_draw_add_task(layer, &a, LV_DRAW_TASK_TYPE_LINE);
|
||||
|
||||
lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc));
|
||||
|
||||
if(dsc->points) {
|
||||
lv_draw_line_dsc_t * new_draw_dsc = t->draw_dsc;
|
||||
size_t array_size = dsc->point_cnt * sizeof(lv_point_precise_t);
|
||||
lv_point_precise_t * new_points = lv_malloc(array_size);
|
||||
lv_memcpy(new_points, dsc->points, array_size);
|
||||
new_draw_dsc->points = new_points;
|
||||
}
|
||||
|
||||
lv_draw_finalize_task_creation(layer, t);
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
|
||||
void lv_draw_line_iterate(lv_draw_task_t * t, lv_draw_line_dsc_t * dsc,
|
||||
void (*draw_line_cb)(lv_draw_task_t * t, const lv_draw_line_dsc_t * dsc))
|
||||
{
|
||||
uint32_t i;
|
||||
lv_point_precise_t * points = dsc->points;
|
||||
if(points == NULL) {
|
||||
draw_line_cb(t, dsc);
|
||||
}
|
||||
else {
|
||||
/*Create a temporary dsc where the point array is replaced by 2 points*/
|
||||
lv_draw_line_dsc_t dsc_tmp = *dsc;
|
||||
size_t point_cnt = dsc_tmp.point_cnt;
|
||||
if(point_cnt <= 1) return;
|
||||
|
||||
dsc_tmp.points = NULL;
|
||||
dsc_tmp.point_cnt = 0;
|
||||
for(i = 0; i < point_cnt - 1; i++) {
|
||||
if(points[i].x == LV_DRAW_LINE_POINT_NONE ||
|
||||
points[i].y == LV_DRAW_LINE_POINT_NONE) {
|
||||
continue;
|
||||
}
|
||||
if(points[i + 1].x == LV_DRAW_LINE_POINT_NONE ||
|
||||
points[i + 1].y == LV_DRAW_LINE_POINT_NONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dsc_tmp.p1 = points[i];
|
||||
dsc_tmp.p2 = points[i + 1];
|
||||
|
||||
draw_line_cb(t, &dsc_tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
+30
-2
@@ -21,19 +21,36 @@ extern "C" {
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#if LV_USE_FLOAT
|
||||
#include <float.h>
|
||||
#define LV_DRAW_LINE_POINT_NONE FLT_MAX
|
||||
#else
|
||||
#define LV_DRAW_LINE_POINT_NONE INT32_MAX
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_draw_dsc_base_t base;
|
||||
|
||||
/**The first point of the line. If `LV_USE_FLOAT` is enabled float number can be also used*/
|
||||
/**The first point of the line. If `LV_USE_FLOAT` is enabled float number can be also used.
|
||||
*Ignored if `points` are set*/
|
||||
lv_point_precise_t p1;
|
||||
|
||||
/**The second point of the line. If `LV_USE_FLOAT` is enabled float number can be also used*/
|
||||
/**The second point of the line. If `LV_USE_FLOAT` is enabled float number can be also used
|
||||
* Ignored if `points` are set*/
|
||||
lv_point_precise_t p2;
|
||||
|
||||
/**Array of points to draw. If `LV_USE_FLOAT` is enabled, float numbers can also be used.*/
|
||||
lv_point_precise_t * points;
|
||||
|
||||
/**
|
||||
* Number of points in the `points`
|
||||
*/
|
||||
int32_t point_cnt;
|
||||
|
||||
/**The color of the line*/
|
||||
lv_color_t color;
|
||||
|
||||
@@ -84,6 +101,17 @@ lv_draw_line_dsc_t * lv_draw_task_get_line_dsc(lv_draw_task_t * task);
|
||||
*/
|
||||
void lv_draw_line(lv_layer_t * layer, const lv_draw_line_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* A helper function to call a callback which draws a line between two points.
|
||||
* This way it doesn't matter if ``p1, p2`` or ``points`` were used as it calls the
|
||||
* ``callback`` as needed.
|
||||
* @param t draw task
|
||||
* @param dsc pointer to a draw descriptor
|
||||
* @param draw_line_cb a callback that draws a line between ``dsc->p1`` and ``dsc->p2``
|
||||
*/
|
||||
void lv_draw_line_iterate(lv_draw_task_t * t, lv_draw_line_dsc_t * dsc,
|
||||
void (*draw_line_cb)(lv_draw_task_t * t, const lv_draw_line_dsc_t * dsc));
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
@@ -324,7 +324,7 @@ static void nema_gfx_execute_drawing(lv_draw_nema_gfx_unit_t * u)
|
||||
lv_draw_nema_gfx_layer(t, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LINE:
|
||||
lv_draw_nema_gfx_line(t, t->draw_dsc);
|
||||
lv_draw_line_iterate(t, t->draw_dsc, lv_draw_nema_gfx_line);
|
||||
break;
|
||||
#if LV_USE_NEMA_VG
|
||||
case LV_DRAW_TASK_TYPE_ARC:
|
||||
|
||||
@@ -538,6 +538,13 @@ static void draw_from_cached_texture(lv_draw_task_t * t)
|
||||
lv_cache_drop(u->texture_cache, &data_to_find, u);
|
||||
}
|
||||
}
|
||||
/*Do not cache lines rendered from points at dsc->points will be freed*/
|
||||
else if(t->type == LV_DRAW_TASK_TYPE_LINE) {
|
||||
lv_draw_line_dsc_t * line_dsc = t->draw_dsc;
|
||||
if(line_dsc->points) {
|
||||
lv_cache_drop(u->texture_cache, &data_to_find, u);
|
||||
}
|
||||
}
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define DRAW_UNIT_ID_DAVE2D 4
|
||||
/* The amount of tasks exercising pressure to the currrent to get finished
|
||||
/* The amount of tasks exercising pressure to the current to get finished
|
||||
* This one is used as the main signal to start to render a block of tasks.
|
||||
*/
|
||||
#define DAVE2D_MAX_DRAW_PRESSURE 256
|
||||
@@ -385,7 +385,7 @@ static int32_t lv_draw_dave2d_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t *
|
||||
t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_DAVE2D);
|
||||
if(t == NULL) {
|
||||
/* No valid task, but there are tasks waiting to be rendered,
|
||||
* start to draw then immediatelly.
|
||||
* start to draw then immediately.
|
||||
*/
|
||||
if(false == lv_ll_is_empty(&draw_tasks_on_dlist)) {
|
||||
draw_pressure = 0;
|
||||
@@ -519,7 +519,7 @@ static void execute_drawing(lv_draw_dave2d_unit_t * u)
|
||||
lv_draw_dave2d_image(t, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LINE:
|
||||
lv_draw_dave2d_line(t, t->draw_dsc);
|
||||
lv_draw_line_iterate(t, t->draw_dsc, lv_draw_dave2d_line);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_ARC:
|
||||
lv_draw_dave2d_arc(t, t->draw_dsc, &t->area);
|
||||
|
||||
@@ -473,6 +473,13 @@ static void draw_from_cached_texture(lv_draw_sdl_unit_t * u)
|
||||
lv_cache_drop(u->texture_cache, &data_to_find, NULL);
|
||||
}
|
||||
}
|
||||
/*Do not cache lines rendered from points at dsc->points will be freed*/
|
||||
else if(t->type == LV_DRAW_TASK_TYPE_LINE) {
|
||||
lv_draw_line_dsc_t * line_dsc = t->draw_dsc;
|
||||
if(line_dsc->points) {
|
||||
lv_cache_drop(u->texture_cache, &data_to_find, u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void execute_drawing(lv_draw_sdl_unit_t * u)
|
||||
|
||||
@@ -408,7 +408,7 @@ static void execute_drawing(lv_draw_task_t * t)
|
||||
lv_draw_sw_arc(t, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LINE:
|
||||
lv_draw_sw_line(t, t->draw_dsc);
|
||||
lv_draw_line_iterate(t, t->draw_dsc, lv_draw_sw_line);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_BLUR:
|
||||
lv_draw_sw_blur(t, t->draw_dsc, &t->area);
|
||||
|
||||
@@ -167,7 +167,7 @@ static void draw_execute(lv_draw_vg_lite_unit_t * u)
|
||||
lv_draw_vg_lite_arc(t, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LINE:
|
||||
lv_draw_vg_lite_line(t, t->draw_dsc);
|
||||
lv_draw_line_iterate(t, t->draw_dsc, lv_draw_vg_lite_line);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LAYER:
|
||||
lv_draw_vg_lite_layer(t, t->draw_dsc, &t->area);
|
||||
|
||||
+105
-92
@@ -1018,7 +1018,9 @@ static void draw_series_line(lv_obj_t * obj, lv_layer_t * layer)
|
||||
lv_chart_t * chart = (lv_chart_t *)obj;
|
||||
if(chart->point_cnt < 2) return;
|
||||
|
||||
uint32_t i;
|
||||
uint32_t ser_cnt = lv_ll_get_len(&chart->series_ll);
|
||||
if(ser_cnt == 0) return;
|
||||
|
||||
int32_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN);
|
||||
int32_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width;
|
||||
int32_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width;
|
||||
@@ -1032,136 +1034,147 @@ static void draw_series_line(lv_obj_t * obj, lv_layer_t * layer)
|
||||
lv_draw_line_dsc_init(&line_dsc);
|
||||
line_dsc.base.layer = layer;
|
||||
lv_obj_init_draw_line_dsc(obj, LV_PART_ITEMS, &line_dsc);
|
||||
|
||||
lv_draw_rect_dsc_t point_dsc_default;
|
||||
lv_draw_rect_dsc_init(&point_dsc_default);
|
||||
point_dsc_default.base.layer = layer;
|
||||
lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &point_dsc_default);
|
||||
|
||||
int32_t point_w = lv_obj_get_style_width(obj, LV_PART_INDICATOR) / 2;
|
||||
int32_t point_h = lv_obj_get_style_height(obj, LV_PART_INDICATOR) / 2;
|
||||
line_dsc.base.id1 = ser_cnt - 1;
|
||||
|
||||
/*If there are at least as many points as pixels then draw only vertical lines*/
|
||||
bool crowded_mode = (int32_t)chart->point_cnt >= w;
|
||||
|
||||
uint32_t ser_cnt = lv_ll_get_len(&chart->series_ll);
|
||||
if(ser_cnt == 0) {
|
||||
int32_t bullet_w = lv_obj_get_style_width(obj, LV_PART_INDICATOR) / 2;
|
||||
int32_t bullet_h = lv_obj_get_style_height(obj, LV_PART_INDICATOR) / 2;
|
||||
int32_t extra_space_x = w / (chart->point_cnt - 1) + bullet_w + line_dsc.width;
|
||||
|
||||
lv_draw_rect_dsc_t point_draw_dsc;
|
||||
if(crowded_mode == false) {
|
||||
lv_draw_rect_dsc_init(&point_draw_dsc);
|
||||
lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &point_draw_dsc);
|
||||
point_draw_dsc.base.id1 = line_dsc.base.id1;
|
||||
}
|
||||
|
||||
lv_point_precise_t * points = NULL;
|
||||
if(crowded_mode) {
|
||||
points = lv_malloc((w + 2 * extra_space_x) * 3 * sizeof(lv_point_precise_t));
|
||||
}
|
||||
else {
|
||||
points = lv_malloc(chart->point_cnt * sizeof(lv_point_precise_t));
|
||||
}
|
||||
|
||||
if(points == NULL) {
|
||||
LV_LOG_WARN("Couldn't allocate the points array");
|
||||
return;
|
||||
}
|
||||
|
||||
line_dsc.base.id1 = ser_cnt - 1;
|
||||
point_dsc_default.base.id1 = line_dsc.base.id1;
|
||||
line_dsc.points = points;
|
||||
|
||||
/*Go through all data lines*/
|
||||
LV_LL_READ_BACK(&chart->series_ll, ser) {
|
||||
if(ser->hidden) {
|
||||
if(line_dsc.base.id1 > 0) {
|
||||
line_dsc.base.id1--;
|
||||
point_dsc_default.base.id1--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
line_dsc.color = ser->color;
|
||||
line_dsc.base.drop_shadow_color = ser->color;
|
||||
point_dsc_default.bg_color = ser->color;
|
||||
point_draw_dsc.bg_color = ser->color;
|
||||
line_dsc.base.id2 = 0;
|
||||
point_dsc_default.base.id2 = 0;
|
||||
|
||||
int32_t start_point = chart->update_mode == LV_CHART_UPDATE_MODE_SHIFT ? ser->start_point : 0;
|
||||
|
||||
line_dsc.p1.x = x_ofs;
|
||||
line_dsc.p2.x = x_ofs;
|
||||
|
||||
int32_t p_act = start_point;
|
||||
int32_t p_prev = start_point;
|
||||
int32_t y_tmp = (int32_t)((int32_t)ser->y_points[p_prev] - chart->ymin[ser->y_axis_sec]) * h;
|
||||
y_tmp = y_tmp / (chart->ymax[ser->y_axis_sec] - chart->ymin[ser->y_axis_sec]);
|
||||
line_dsc.p2.y = h - y_tmp + y_ofs;
|
||||
|
||||
lv_value_precise_t y_min = line_dsc.p2.y;
|
||||
lv_value_precise_t y_max = line_dsc.p2.y;
|
||||
lv_value_precise_t y_min = obj->coords.y2;
|
||||
lv_value_precise_t y_max = obj->coords.y1;
|
||||
lv_value_precise_t x_prev = -10000;
|
||||
line_dsc.p1.x = x_ofs;
|
||||
line_dsc.p2.x = x_ofs;
|
||||
line_dsc.point_cnt = 0;
|
||||
|
||||
uint32_t i;
|
||||
for(i = 0; i < chart->point_cnt; i++) {
|
||||
line_dsc.p1.x = line_dsc.p2.x;
|
||||
line_dsc.p1.y = line_dsc.p2.y;
|
||||
|
||||
if(line_dsc.p1.x > layer->_clip_area.x2 + point_w + 1) break;
|
||||
line_dsc.p2.x = (lv_value_precise_t)((w * i) / (chart->point_cnt - 1)) + x_ofs;
|
||||
|
||||
p_act = (start_point + i) % chart->point_cnt;
|
||||
|
||||
y_tmp = (int32_t)((int32_t)ser->y_points[p_act] - chart->ymin[ser->y_axis_sec]) * h;
|
||||
y_tmp = y_tmp / (chart->ymax[ser->y_axis_sec] - chart->ymin[ser->y_axis_sec]);
|
||||
line_dsc.p2.y = h - y_tmp + y_ofs;
|
||||
|
||||
if(line_dsc.p2.x < layer->_clip_area.x1 - point_w - 1) {
|
||||
lv_value_precise_t p_x = (int32_t)((w * i) / (chart->point_cnt - 1)) + x_ofs;
|
||||
if(p_x > layer->_clip_area.x2 + extra_space_x + 1) break;
|
||||
if(p_x < layer->_clip_area.x1 - extra_space_x - 1) {
|
||||
p_prev = p_act;
|
||||
continue;
|
||||
}
|
||||
p_act = (start_point + i) % chart->point_cnt;
|
||||
|
||||
/*Don't draw the first point. A second point is also required to draw the line*/
|
||||
if(i != 0) {
|
||||
if(crowded_mode) {
|
||||
if(ser->y_points[p_prev] != LV_CHART_POINT_NONE && ser->y_points[p_act] != LV_CHART_POINT_NONE) {
|
||||
/*Draw only one vertical line between the min and max y-values on the same x-value*/
|
||||
y_max = LV_MAX(y_max, line_dsc.p2.y);
|
||||
y_min = LV_MIN(y_min, line_dsc.p2.y);
|
||||
if(line_dsc.p1.x != line_dsc.p2.x) {
|
||||
lv_value_precise_t y_cur = line_dsc.p2.y;
|
||||
line_dsc.p2.x--; /*It's already on the next x value*/
|
||||
line_dsc.p1.x = line_dsc.p2.x;
|
||||
line_dsc.p1.y = y_min;
|
||||
line_dsc.p2.y = y_max;
|
||||
if(line_dsc.p1.y == line_dsc.p2.y) line_dsc.p2.y++; /*If they are the same no line will be drawn*/
|
||||
lv_draw_line(layer, &line_dsc);
|
||||
line_dsc.p2.x++; /*Compensate the previous x--*/
|
||||
y_min = y_cur; /*Start the line of the next x from the current last y*/
|
||||
y_max = y_cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_area_t point_area;
|
||||
point_area.x1 = (int32_t)line_dsc.p1.x - point_w;
|
||||
point_area.x2 = (int32_t)line_dsc.p1.x + point_w;
|
||||
point_area.y1 = (int32_t)line_dsc.p1.y - point_h;
|
||||
point_area.y2 = (int32_t)line_dsc.p1.y + point_h;
|
||||
|
||||
if(ser->y_points[p_prev] != LV_CHART_POINT_NONE && ser->y_points[p_act] != LV_CHART_POINT_NONE) {
|
||||
line_dsc.base.id2 = i;
|
||||
lv_draw_line(layer, &line_dsc);
|
||||
}
|
||||
|
||||
if(point_w && point_h && ser->y_points[p_prev] != LV_CHART_POINT_NONE) {
|
||||
point_dsc_default.base.id2 = i - 1;
|
||||
lv_draw_rect(layer, &point_dsc_default, &point_area);
|
||||
}
|
||||
}
|
||||
|
||||
lv_value_precise_t p_y;
|
||||
if(ser->y_points[p_act] == LV_CHART_POINT_NONE) {
|
||||
p_y = LV_DRAW_LINE_POINT_NONE;
|
||||
}
|
||||
else {
|
||||
int32_t v = ser->y_points[p_act];
|
||||
int32_t min_v = chart->ymin[ser->y_axis_sec];
|
||||
int32_t max_v = chart->ymax[ser->y_axis_sec];
|
||||
p_y = (int32_t)lv_map(v, min_v, max_v, y_ofs + h, y_ofs);
|
||||
}
|
||||
|
||||
/*In normal mode just collect the points here*/
|
||||
if(crowded_mode == false) {
|
||||
points[line_dsc.point_cnt].x = p_x;
|
||||
points[line_dsc.point_cnt].y = p_y;
|
||||
line_dsc.point_cnt++;
|
||||
}
|
||||
/*In crowded mode draw vertical lines from the min/max on the same X coordinate*/
|
||||
else {
|
||||
if(ser->y_points[p_prev] != LV_CHART_POINT_NONE && ser->y_points[p_act] != LV_CHART_POINT_NONE) {
|
||||
/*Draw only one vertical line between the min and max y-values on the same x-value*/
|
||||
y_max = LV_MAX(y_max, p_y);
|
||||
y_min = LV_MIN(y_min, p_y);
|
||||
if(x_prev != p_x) {
|
||||
line_dsc.points[line_dsc.point_cnt].y = y_min;
|
||||
line_dsc.points[line_dsc.point_cnt].x = p_x;
|
||||
line_dsc.points[line_dsc.point_cnt + 1].y = y_max;
|
||||
line_dsc.points[line_dsc.point_cnt + 1].x = p_x;
|
||||
line_dsc.points[line_dsc.point_cnt + 2].y = LV_DRAW_LINE_POINT_NONE;
|
||||
line_dsc.points[line_dsc.point_cnt + 2].x = p_x;
|
||||
|
||||
/*If they are the same no line would be drawn*/
|
||||
if(line_dsc.points[line_dsc.point_cnt].y == line_dsc.points[line_dsc.point_cnt + 1].y) {
|
||||
line_dsc.points[line_dsc.point_cnt + 1].y++;
|
||||
}
|
||||
y_min = p_y; /*Start the line of the next x from the current last y*/
|
||||
y_max = p_y;
|
||||
x_prev = p_x;
|
||||
line_dsc.point_cnt += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p_prev = p_act;
|
||||
}
|
||||
|
||||
/*Draw the last point*/
|
||||
if(!crowded_mode && i == chart->point_cnt) {
|
||||
/*Draw the line from the accumulated points*/
|
||||
lv_draw_line(layer, &line_dsc);
|
||||
if(!crowded_mode) {
|
||||
point_draw_dsc.bg_color = ser->color;
|
||||
point_draw_dsc.base.id1 = line_dsc.base.id1;
|
||||
/*Add the bullets too*/
|
||||
if(bullet_w > 0 && bullet_h > 0) {
|
||||
point_draw_dsc.base.id2 = i - 1; /*Start from the last rendered point*/
|
||||
int32_t j;
|
||||
for(j = line_dsc.point_cnt - 1; j >= 0; j--) {
|
||||
if(points[j].y == LV_DRAW_LINE_POINT_NONE) continue;
|
||||
|
||||
if(ser->y_points[p_act] != LV_CHART_POINT_NONE) {
|
||||
lv_area_t point_area;
|
||||
point_area.x1 = (int32_t)line_dsc.p2.x - point_w;
|
||||
point_area.x2 = (int32_t)line_dsc.p2.x + point_w;
|
||||
point_area.y1 = (int32_t)line_dsc.p2.y - point_h;
|
||||
point_area.y2 = (int32_t)line_dsc.p2.y + point_h;
|
||||
point_dsc_default.base.id2 = i - 1;
|
||||
lv_draw_rect(layer, &point_dsc_default, &point_area);
|
||||
lv_area_t point_area;
|
||||
point_area.x1 = (int32_t)points[j].x - bullet_w;
|
||||
point_area.x2 = (int32_t)points[j].x + bullet_w;
|
||||
point_area.y1 = (int32_t)points[j].y - bullet_h;
|
||||
point_area.y2 = (int32_t)points[j].y + bullet_h;
|
||||
|
||||
lv_draw_rect(layer, &point_draw_dsc, &point_area);
|
||||
point_draw_dsc.base.id2--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(line_dsc.base.id1 > 0) {
|
||||
point_dsc_default.base.id1--;
|
||||
line_dsc.base.id1--;
|
||||
}
|
||||
line_dsc.base.id1--;
|
||||
}
|
||||
|
||||
if(points) lv_free(points);
|
||||
}
|
||||
|
||||
|
||||
static void draw_series_scatter(lv_obj_t * obj, lv_layer_t * layer)
|
||||
{
|
||||
lv_chart_t * chart = (lv_chart_t *)obj;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 76 KiB |
Reference in New Issue
Block a user