1 /**
2 * @file lv_draw_vg_lite_line.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9
10 #include "../../misc/lv_area_private.h"
11 #include "lv_draw_vg_lite.h"
12
13 #if LV_USE_DRAW_VG_LITE
14
15 #include "lv_draw_vg_lite_type.h"
16 #include "lv_vg_lite_math.h"
17 #include "lv_vg_lite_path.h"
18 #include "lv_vg_lite_utils.h"
19
20 /*********************
21 * DEFINES
22 *********************/
23
24 #define SQ(x) ((x) * (x))
25
26 /**********************
27 * TYPEDEFS
28 **********************/
29
30 /**********************
31 * STATIC PROTOTYPES
32 **********************/
33
34 /**********************
35 * STATIC VARIABLES
36 **********************/
37
38 /**********************
39 * MACROS
40 **********************/
41
42 /**********************
43 * GLOBAL FUNCTIONS
44 **********************/
45
lv_draw_vg_lite_line(lv_draw_unit_t * draw_unit,const lv_draw_line_dsc_t * dsc)46 void lv_draw_vg_lite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc)
47 {
48 float p1_x = dsc->p1.x;
49 float p1_y = dsc->p1.y;
50 float p2_x = dsc->p2.x;
51 float p2_y = dsc->p2.y;
52
53 if(p1_x == p2_x && p1_y == p2_y)
54 return;
55
56 float half_w = dsc->width * 0.5f;
57
58 lv_area_t rel_clip_area;
59 rel_clip_area.x1 = (int32_t)(LV_MIN(p1_x, p2_x) - half_w);
60 rel_clip_area.x2 = (int32_t)(LV_MAX(p1_x, p2_x) + half_w);
61 rel_clip_area.y1 = (int32_t)(LV_MIN(p1_y, p2_y) - half_w);
62 rel_clip_area.y2 = (int32_t)(LV_MAX(p1_y, p2_y) + half_w);
63
64 if(!lv_area_intersect(&rel_clip_area, &rel_clip_area, draw_unit->clip_area)) {
65 return; /*Fully clipped, nothing to do*/
66 }
67
68 LV_PROFILER_DRAW_BEGIN;
69
70 lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit;
71
72 int32_t dash_width = dsc->dash_width;
73 int32_t dash_gap = dsc->dash_gap;
74 int32_t dash_l = dash_width + dash_gap;
75
76 float dx = p2_x - p1_x;
77 float dy = p2_y - p1_y;
78 float inv_dl = math_fast_inv_sqrtf(SQ(dx) + SQ(dy));
79 float w_dx = dsc->width * dy * inv_dl;
80 float w_dy = dsc->width * dx * inv_dl;
81 float w2_dx = w_dx / 2;
82 float w2_dy = w_dy / 2;
83
84 int32_t ndash = 0;
85 if(dash_width && dash_l * inv_dl < 1.0f) {
86 ndash = (int32_t)((1.0f / inv_dl + dash_l - 1) / dash_l);
87 }
88
89 lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_FP32);
90 lv_vg_lite_path_set_bounding_box_area(path, &rel_clip_area);
91
92 /* head point */
93 float head_start_x = p1_x + w2_dx;
94 float head_start_y = p1_y - w2_dy;
95 float head_end_x = p1_x - w2_dx;
96 float head_end_y = p1_y + w2_dy;
97
98 /* tail point */
99 float tail_start_x = p2_x - w2_dx;
100 float tail_start_y = p2_y + w2_dy;
101 float tail_end_x = p2_x + w2_dx;
102 float tail_end_y = p2_y - w2_dy;
103
104 /*
105 head_start tail_end
106 *-----------------*
107 /| |\
108 / | | \
109 arc_c *( *p1 p2* )* arc_c
110 \ | | /
111 \| |/
112 *-----------------*
113 head_end tail_start
114 */
115
116 /* move to start point */
117 lv_vg_lite_path_move_to(path, head_start_x, head_start_y);
118
119 /* draw line head */
120 if(dsc->round_start) {
121 float arc_cx = p1_x - w2_dy;
122 float arc_cy = p1_y - w2_dx;
123
124 /* start 90deg arc */
125 lv_vg_lite_path_append_arc_right_angle(path,
126 head_start_x, head_start_y,
127 p1_x, p1_y,
128 arc_cx, arc_cy);
129
130 /* end 90deg arc */
131 lv_vg_lite_path_append_arc_right_angle(path,
132 arc_cx, arc_cy,
133 p1_x, p1_y,
134 head_end_x, head_end_y);
135 }
136 else {
137 lv_vg_lite_path_line_to(path, head_end_x, head_end_y);
138 }
139
140 /* draw line body */
141 lv_vg_lite_path_line_to(path, tail_start_x, tail_start_y);
142
143 /* draw line tail */
144 if(dsc->round_end) {
145 float arc_cx = p2_x + w2_dy;
146 float arc_cy = p2_y + w2_dx;
147 lv_vg_lite_path_append_arc_right_angle(path,
148 tail_start_x, tail_start_y,
149 p2_x, p2_y,
150 arc_cx, arc_cy);
151 lv_vg_lite_path_append_arc_right_angle(path,
152 arc_cx, arc_cy,
153 p2_x, p2_y,
154 tail_end_x, tail_end_y);
155 }
156 else {
157 lv_vg_lite_path_line_to(path, tail_end_x, tail_end_y);
158 }
159
160 /* close draw line body */
161 lv_vg_lite_path_line_to(path, head_start_x, head_start_y);
162
163 for(int32_t i = 0; i < ndash; i++) {
164 float start_x = p1_x - w2_dx + dx * (i * dash_l + dash_width) * inv_dl;
165 float start_y = p1_y + w2_dy + dy * (i * dash_l + dash_width) * inv_dl;
166
167 lv_vg_lite_path_move_to(path, start_x, start_y);
168 lv_vg_lite_path_line_to(path,
169 p1_x + w2_dx + dx * (i * dash_l + dash_width) * inv_dl,
170 p1_y - w2_dy + dy * (i * dash_l + dash_width) * inv_dl);
171 lv_vg_lite_path_line_to(path,
172 p1_x + w2_dx + dx * (i + 1) * dash_l * inv_dl,
173 p1_y - w2_dy + dy * (i + 1) * dash_l * inv_dl);
174 lv_vg_lite_path_line_to(path,
175 p1_x - w2_dx + dx * (i + 1) * dash_l * inv_dl,
176 p1_y + w2_dy + dy * (i + 1) * dash_l * inv_dl);
177 lv_vg_lite_path_line_to(path, start_x, start_y);
178 }
179
180 lv_vg_lite_path_end(path);
181
182 vg_lite_matrix_t matrix = u->global_matrix;
183
184 vg_lite_color_t color = lv_vg_lite_color(dsc->color, dsc->opa, true);
185
186 vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path);
187
188 LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer);
189 LV_VG_LITE_ASSERT_PATH(vg_lite_path);
190 LV_VG_LITE_ASSERT_MATRIX(&matrix);
191
192 LV_PROFILER_DRAW_BEGIN_TAG("vg_lite_draw");
193 LV_VG_LITE_CHECK_ERROR(vg_lite_draw(
194 &u->target_buffer,
195 vg_lite_path,
196 VG_LITE_FILL_EVEN_ODD,
197 &matrix,
198 VG_LITE_BLEND_SRC_OVER,
199 color));
200 LV_PROFILER_DRAW_END_TAG("vg_lite_draw");
201
202 lv_vg_lite_path_drop(u, path);
203
204 LV_PROFILER_DRAW_END;
205 }
206
207 /**********************
208 * STATIC FUNCTIONS
209 **********************/
210
211 #endif /*LV_USE_DRAW_VG_LITE*/
212