1 /**
2 * @file lv_draw_vg_lite_arc.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9
10 #include "../../misc/lv_area_private.h"
11 #include "../lv_image_decoder_private.h"
12 #include "../lv_draw_private.h"
13 #include "lv_draw_vg_lite.h"
14
15 #if LV_USE_DRAW_VG_LITE
16
17 #include "lv_draw_vg_lite_type.h"
18 #include "lv_vg_lite_math.h"
19 #include "lv_vg_lite_path.h"
20 #include "lv_vg_lite_pending.h"
21 #include "lv_vg_lite_utils.h"
22 #include <math.h>
23
24 /*********************
25 * DEFINES
26 *********************/
27
28 #define PI 3.1415926535897932384626433832795f
29 #define TWO_PI 6.283185307179586476925286766559f
30 #define DEG_TO_RAD 0.017453292519943295769236907684886f
31 #define RAD_TO_DEG 57.295779513082320876798154814105f
32 #define radians(deg) ((deg) * DEG_TO_RAD)
33 #define degrees(rad) ((rad) * RAD_TO_DEG)
34
35 /**********************
36 * TYPEDEFS
37 **********************/
38
39 /**********************
40 * STATIC PROTOTYPES
41 **********************/
42
43 /**********************
44 * STATIC VARIABLES
45 **********************/
46
47 /**********************
48 * MACROS
49 **********************/
50
51 /**********************
52 * GLOBAL FUNCTIONS
53 **********************/
54
lv_draw_vg_lite_arc(lv_draw_unit_t * draw_unit,const lv_draw_arc_dsc_t * dsc,const lv_area_t * coords)55 void lv_draw_vg_lite_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc,
56 const lv_area_t * coords)
57 {
58 lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit;
59
60 lv_area_t clip_area;
61 if(!lv_area_intersect(&clip_area, coords, draw_unit->clip_area)) {
62 /*Fully clipped, nothing to do*/
63 return;
64 }
65
66 float start_angle = dsc->start_angle;
67 float end_angle = dsc->end_angle;
68 float sweep_angle = end_angle - start_angle;
69
70 while(sweep_angle < 0) {
71 sweep_angle += 360;
72 }
73
74 while(sweep_angle > 360) {
75 sweep_angle -= 360;
76 }
77
78 /*If the angles are the same then there is nothing to draw*/
79 if(math_zero(sweep_angle)) {
80 return;
81 }
82
83 LV_PROFILER_DRAW_BEGIN;
84
85 lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_FP32);
86 lv_vg_lite_path_set_bounding_box_area(path, &clip_area);
87
88 float radius_out = dsc->radius;
89 float radius_in = dsc->radius - dsc->width;
90 float cx = dsc->center.x;
91 float cy = dsc->center.y;
92
93 vg_lite_fill_t fill = VG_LITE_FILL_NON_ZERO;
94
95 if(math_equal(sweep_angle, 360)) {
96 lv_vg_lite_path_append_circle(path, cx, cy, radius_out, radius_out);
97
98 /* radius_in <= 0, normal fill circle */
99 if(radius_in > 0) {
100 lv_vg_lite_path_append_circle(path, cx, cy, radius_in, radius_in);
101 }
102 fill = VG_LITE_FILL_EVEN_ODD;
103 }
104 else {
105 float start_angle_rad = MATH_RADIANS(start_angle);
106 float end_angle_rad = MATH_RADIANS(end_angle);
107
108 if(radius_in > 0) {
109 /* radius_out start point */
110 float start_x = radius_out * MATH_COSF(start_angle_rad) + cx;
111 float start_y = radius_out * MATH_SINF(start_angle_rad) + cy;
112
113 /* radius_in start point */
114 float end_x = radius_in * MATH_COSF(end_angle_rad) + cx;
115 float end_y = radius_in * MATH_SINF(end_angle_rad) + cy;
116
117 lv_vg_lite_path_move_to(path, start_x, start_y);
118
119 /* radius_out arc */
120 lv_vg_lite_path_append_arc(path,
121 cx, cy,
122 radius_out,
123 start_angle,
124 sweep_angle,
125 false);
126
127 /* line to radius_in */
128 lv_vg_lite_path_line_to(path, end_x, end_y);
129
130 /* radius_in arc */
131 lv_vg_lite_path_append_arc(path,
132 cx, cy,
133 radius_in,
134 end_angle,
135 -sweep_angle,
136 false);
137
138 /* close arc */
139 lv_vg_lite_path_close(path);
140 }
141 else {
142 /* draw a normal arc pie shape */
143 lv_vg_lite_path_append_arc(path, cx, cy, radius_out, start_angle, sweep_angle, true);
144 }
145
146 /* draw round */
147 if(dsc->rounded && dsc->width > 0) {
148 float round_radius = radius_out > dsc->width ? dsc->width / 2.0f : radius_out / 2.0f;
149 float round_center = radius_out - round_radius;
150 float rcx1 = cx + round_center * MATH_COSF(end_angle_rad);
151 float rcy1 = cy + round_center * MATH_SINF(end_angle_rad);
152 lv_vg_lite_path_append_circle(path, rcx1, rcy1, round_radius, round_radius);
153
154 float rcx2 = cx + round_center * MATH_COSF(start_angle_rad);
155 float rcy2 = cy + round_center * MATH_SINF(start_angle_rad);
156 lv_vg_lite_path_append_circle(path, rcx2, rcy2, round_radius, round_radius);
157 }
158 }
159
160 lv_vg_lite_path_end(path);
161 vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path);
162
163 vg_lite_matrix_t matrix = u->global_matrix;
164
165 LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer);
166 LV_VG_LITE_ASSERT_PATH(vg_lite_path);
167 LV_VG_LITE_ASSERT_MATRIX(&matrix);
168
169 if(dsc->img_src) {
170 vg_lite_buffer_t src_buf;
171 lv_image_decoder_dsc_t decoder_dsc;
172 if(lv_vg_lite_buffer_open_image(&src_buf, &decoder_dsc, dsc->img_src, false, true)) {
173
174 vg_lite_color_t img_color = 0;
175 if(dsc->opa < LV_OPA_COVER) {
176 /* normal image opa */
177 src_buf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
178 lv_memset(&img_color, dsc->opa, sizeof(img_color));
179 }
180
181 vg_lite_matrix_t path_matrix = u->global_matrix;
182
183 /* move image to center */
184 float img_half_w = decoder_dsc.decoded->header.w / 2.0f;
185 float img_half_h = decoder_dsc.decoded->header.h / 2.0f;
186 vg_lite_translate(cx - img_half_w, cy - img_half_h, &matrix);
187
188 LV_VG_LITE_ASSERT_MATRIX(&matrix);
189 LV_VG_LITE_ASSERT_MATRIX(&path_matrix);
190 LV_VG_LITE_ASSERT_SRC_BUFFER(&src_buf);
191
192 LV_PROFILER_DRAW_BEGIN_TAG("vg_lite_draw_pattern");
193 LV_VG_LITE_CHECK_ERROR(vg_lite_draw_pattern(
194 &u->target_buffer,
195 vg_lite_path,
196 fill,
197 &path_matrix,
198 &src_buf,
199 &matrix,
200 VG_LITE_BLEND_SRC_OVER,
201 VG_LITE_PATTERN_COLOR,
202 0,
203 img_color,
204 VG_LITE_FILTER_BI_LINEAR));
205 LV_PROFILER_DRAW_END_TAG("vg_lite_draw_pattern");
206 lv_vg_lite_pending_add(u->image_dsc_pending, &decoder_dsc);
207 }
208 }
209 else {
210 /* normal color fill */
211 LV_PROFILER_DRAW_BEGIN_TAG("vg_lite_draw");
212 LV_VG_LITE_CHECK_ERROR(vg_lite_draw(
213 &u->target_buffer,
214 vg_lite_path,
215 fill,
216 &matrix,
217 VG_LITE_BLEND_SRC_OVER,
218 lv_vg_lite_color(dsc->color, dsc->opa, true)));
219 LV_PROFILER_DRAW_END_TAG("vg_lite_draw");
220 }
221
222 lv_vg_lite_path_drop(u, path);
223 LV_PROFILER_DRAW_END;
224 }
225
226 /**********************
227 * STATIC FUNCTIONS
228 **********************/
229
230 #endif /*LV_USE_DRAW_VG_LITE*/
231