Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
CTCaer
GitHub Repository: CTCaer/hekate
Path: blob/master/bdk/libs/lvgl/lv_draw/lv_draw_line.c
1476 views
1
/**
2
* @file lv_draw_line.c
3
*
4
*/
5
6
/*********************
7
* INCLUDES
8
*********************/
9
#include <stdio.h>
10
#include "lv_draw.h"
11
#include "../lv_misc/lv_math.h"
12
13
/*********************
14
* DEFINES
15
*********************/
16
#if LV_COMPILER_VLA_SUPPORTED == 0
17
#define LINE_MAX_WIDTH 64
18
#endif
19
20
/**********************
21
* TYPEDEFS
22
**********************/
23
24
typedef struct {
25
lv_point_t p1;
26
lv_point_t p2;
27
lv_point_t p_act;
28
lv_coord_t dx;
29
lv_coord_t sx; /*-1: x1 < x2; 1: x2 >= x1*/
30
lv_coord_t dy;
31
lv_coord_t sy; /*-1: y1 < y2; 1: y2 >= y1*/
32
lv_coord_t err;
33
lv_coord_t e2;
34
bool hor; /*Rather horizontal or vertical*/
35
} line_draw_t;
36
37
typedef struct {
38
lv_coord_t width;
39
lv_coord_t width_1;
40
lv_coord_t width_half;
41
} line_width_t;
42
43
/**********************
44
* STATIC PROTOTYPES
45
**********************/
46
static void line_draw_hor(line_draw_t * main_line, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale);
47
static void line_draw_ver(line_draw_t * main_line, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale);
48
static void line_draw_skew(line_draw_t * main_line, bool dir_ori, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale);
49
static void line_init(line_draw_t * line, const lv_point_t * p1, const lv_point_t * p2);
50
static bool line_next(line_draw_t * line);
51
static bool line_next_y(line_draw_t * line);
52
static bool line_next_x(line_draw_t * line);
53
54
/**********************
55
* STATIC VARIABLES
56
**********************/
57
58
/**********************
59
* MACROS
60
**********************/
61
62
/**********************
63
* GLOBAL FUNCTIONS
64
**********************/
65
66
/**
67
* Draw a line
68
* @param point1 first point of the line
69
* @param point2 second point of the line
70
* @param mask the line will be drawn only on this area
71
* @param style pointer to a line's style
72
* @param opa_scale scale down all opacities by the factor
73
*/
74
void lv_draw_line(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * mask,
75
const lv_style_t * style, lv_opa_t opa_scale)
76
{
77
78
if(style->line.width == 0) return;
79
if(point1->x == point2->x && point1->y == point2->y) return;
80
81
line_draw_t main_line;
82
lv_point_t p1;
83
lv_point_t p2;
84
85
/*If the line if rather vertical then be sure y1 < y2 else x1 < x2*/
86
87
if(LV_MATH_ABS(point1->x - point2->x) > LV_MATH_ABS(point1->y - point2->y)) {
88
89
/*Steps less in y then x -> rather horizontal*/
90
if(point1->x < point2->x) {
91
p1.x = point1->x;
92
p1.y = point1->y;
93
p2.x = point2->x;
94
p2.y = point2->y;
95
} else {
96
p1.x = point2->x;
97
p1.y = point2->y;
98
p2.x = point1->x;
99
p2.y = point1->y;
100
}
101
} else {
102
/*Steps less in x then y -> rather vertical*/
103
if(point1->y < point2->y) {
104
p1.x = point1->x;
105
p1.y = point1->y;
106
p2.x = point2->x;
107
p2.y = point2->y;
108
} else {
109
p1.x = point2->x;
110
p1.y = point2->y;
111
p2.x = point1->x;
112
p2.y = point1->y;
113
}
114
}
115
116
line_init(&main_line, &p1, &p2);
117
118
119
/*Special case draw a horizontal line*/
120
if(main_line.p1.y == main_line.p2.y) {
121
line_draw_hor(&main_line, mask, style, opa_scale);
122
}
123
/*Special case draw a vertical line*/
124
else if(main_line.p1.x == main_line.p2.x) {
125
line_draw_ver(&main_line, mask, style, opa_scale);
126
}
127
/*Arbitrary skew line*/
128
else {
129
bool dir_ori = false;
130
#if LV_ANTIALIAS
131
lv_point_t p_tmp;
132
133
if(main_line.hor) {
134
if(main_line.p1.y < main_line.p2.y) {
135
dir_ori = true;
136
p_tmp.x = main_line.p2.x;
137
p_tmp.y = main_line.p2.y - 1;
138
line_init(&main_line, &p1, &p_tmp);
139
main_line.sy = LV_MATH_ABS(main_line.sy); /*The sign can change if the line becomes horizontal*/
140
}
141
else if(main_line.p1.y > main_line.p2.y) {
142
dir_ori = false;
143
p_tmp.x = main_line.p2.x;
144
p_tmp.y = main_line.p2.y + 1;
145
line_init(&main_line, &p1, &p_tmp);
146
main_line.sy = -LV_MATH_ABS(main_line.sy); /*The sign can change if the line becomes horizontal*/
147
}
148
}
149
else {
150
if(main_line.p1.x < main_line.p2.x) {
151
dir_ori = true;
152
p_tmp.x = main_line.p2.x - 1;
153
p_tmp.y = main_line.p2.y;
154
line_init(&main_line, &p1, &p_tmp);
155
main_line.sx = LV_MATH_ABS(main_line.sx); /*The sign can change if the line becomes vertical*/
156
}
157
else if(main_line.p1.x > main_line.p2.x) {
158
dir_ori = false;
159
p_tmp.x = main_line.p2.x + 1;
160
p_tmp.y = main_line.p2.y;
161
line_init(&main_line, &p1, &p_tmp);
162
main_line.sx = -LV_MATH_ABS(main_line.sx); /*The sign can change if the line becomes vertical*/
163
}
164
}
165
#endif
166
line_draw_skew(&main_line, dir_ori, mask, style, opa_scale);
167
}
168
}
169
170
171
/**********************
172
* STATIC FUNCTIONS
173
**********************/
174
175
176
static void line_draw_hor(line_draw_t * main_line, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale)
177
{
178
lv_coord_t width = style->line.width - 1;
179
lv_coord_t width_half = width >> 1;
180
lv_coord_t width_1 = width & 0x1;
181
lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->line.opa : (uint16_t)((uint16_t) style->line.opa * opa_scale) >> 8;
182
183
lv_area_t act_area;
184
act_area.x1 = main_line->p1.x;
185
act_area.x2 = main_line->p2.x;
186
act_area.y1 = main_line->p1.y - width_half - width_1;
187
act_area.y2 = main_line->p2.y + width_half ;
188
189
lv_area_t draw_area;
190
draw_area.x1 = LV_MATH_MIN(act_area.x1, act_area.x2);
191
draw_area.x2 = LV_MATH_MAX(act_area.x1, act_area.x2);
192
draw_area.y1 = LV_MATH_MIN(act_area.y1, act_area.y2);
193
draw_area.y2 = LV_MATH_MAX(act_area.y1, act_area.y2);
194
fill_fp(&draw_area, mask, style->line.color, opa);
195
}
196
197
static void line_draw_ver(line_draw_t * main_line, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale)
198
{
199
lv_coord_t width = style->line.width - 1;
200
lv_coord_t width_half = width >> 1;
201
lv_coord_t width_1 = width & 0x1;
202
lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->line.opa : (uint16_t)((uint16_t) style->line.opa * opa_scale) >> 8;
203
204
205
lv_area_t act_area;
206
act_area.x1 = main_line->p1.x - width_half;
207
act_area.x2 = main_line->p2.x + width_half + width_1;
208
act_area.y1 = main_line->p1.y;
209
act_area.y2 = main_line->p2.y;
210
211
lv_area_t draw_area;
212
draw_area.x1 = LV_MATH_MIN(act_area.x1, act_area.x2);
213
draw_area.x2 = LV_MATH_MAX(act_area.x1, act_area.x2);
214
draw_area.y1 = LV_MATH_MIN(act_area.y1, act_area.y2);
215
draw_area.y2 = LV_MATH_MAX(act_area.y1, act_area.y2);
216
fill_fp(&draw_area, mask, style->line.color, opa);
217
}
218
219
static void line_draw_skew(line_draw_t * main_line, bool dir_ori, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale)
220
{
221
222
lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->line.opa : (uint16_t)((uint16_t) style->line.opa * opa_scale) >> 8;
223
224
lv_point_t vect_main, vect_norm;
225
vect_main.x = main_line->p2.x - main_line->p1.x;
226
vect_main.y = main_line->p2.y - main_line->p1.y;
227
228
if(main_line->hor) {
229
if(main_line->p1.y < main_line->p2.y + dir_ori) {
230
vect_norm.x = - vect_main.y;
231
vect_norm.y = vect_main.x;
232
} else {
233
vect_norm.x = vect_main.y;
234
vect_norm.y = -vect_main.x;
235
}
236
} else {
237
if(main_line->p1.x < main_line->p2.x + dir_ori) {
238
vect_norm.x = vect_main.y;
239
vect_norm.y = - vect_main.x;
240
} else {
241
vect_norm.x = - vect_main.y;
242
vect_norm.y = vect_main.x;
243
}
244
}
245
246
/* In case of a short but tick line the perpendicular ending is longer then the real line.
247
* it would break the calculations so make the normal vector larger*/
248
vect_norm.x = vect_norm.x << 4;
249
vect_norm.y = vect_norm.y << 4;
250
251
lv_coord_t width;
252
width = style->line.width;
253
254
/* The pattern stores the points of the line ending. It has the good direction and length.
255
* The worth case is the 45° line where pattern can have 1.41 x `width` points*/
256
#if LV_COMPILER_VLA_SUPPORTED
257
lv_point_t pattern[width * 2];
258
#else
259
lv_point_t pattern[LINE_MAX_WIDTH];
260
#endif
261
lv_coord_t i = 0;
262
263
/*Create a perpendicular pattern (a small line)*/
264
if(width != 0) {
265
line_draw_t pattern_line;
266
lv_point_t p0 = {0, 0};
267
line_init(&pattern_line, &p0, &vect_norm);
268
269
uint32_t width_sqr = width * width;
270
/* Run for a lot of times. Meanwhile the real width will be determined as well */
271
for(i = 0; i < (lv_coord_t)sizeof(pattern); i ++) {
272
pattern[i].x = pattern_line.p_act.x;
273
pattern[i].y = pattern_line.p_act.y;
274
275
/*Finish the pattern line if it's length equal to the desired width (Use Pythagoras theorem)*/
276
uint32_t sqr = pattern_line.p_act.x * pattern_line.p_act.x + pattern_line.p_act.y * pattern_line.p_act.y;
277
if(sqr >= width_sqr) {
278
width = i;
279
#if LV_ANTIALIAS
280
width--;
281
#endif
282
break;
283
}
284
285
line_next(&pattern_line);
286
}
287
}
288
289
#if LV_ANTIALIAS
290
lv_coord_t width_safe = width;
291
if(width == 0) width_safe = 1;
292
293
lv_coord_t aa_last_corner;
294
aa_last_corner = 0;
295
#endif
296
297
lv_coord_t x_center_ofs = 0;
298
lv_coord_t y_center_ofs = 0;
299
300
if(width != 0) {
301
x_center_ofs = pattern[width - 1].x / 2;
302
y_center_ofs = pattern[width - 1].y / 2;
303
}
304
else {
305
if(main_line->hor && main_line->p1.y >= main_line->p2.y + dir_ori) pattern[0].y --;
306
if(!main_line->hor && main_line->p1.x >= main_line->p2.x + dir_ori) pattern[0].x --;
307
}
308
309
/* Make the coordinates relative to the center */
310
for(i = 0; i < width; i++) {
311
pattern[i].x -= x_center_ofs;
312
pattern[i].y -= y_center_ofs;
313
#if LV_ANTIALIAS
314
if(i != 0) {
315
if(main_line->hor) {
316
if(pattern[i - 1].x != pattern[i].x) {
317
lv_coord_t seg_w = pattern[i].y - pattern[aa_last_corner].y;
318
if(main_line->sy < 0) {
319
lv_draw_aa_ver_seg(main_line->p1.x + pattern[aa_last_corner].x - 1, main_line->p1.y + pattern[aa_last_corner].y + seg_w + 1,
320
seg_w, mask, style->line.color, opa);
321
322
lv_draw_aa_ver_seg(main_line->p2.x + pattern[aa_last_corner].x + 1, main_line->p2.y + pattern[aa_last_corner].y + seg_w + 1,
323
-seg_w, mask, style->line.color, opa);
324
} else {
325
lv_draw_aa_ver_seg(main_line->p1.x + pattern[aa_last_corner].x - 1, main_line->p1.y + pattern[aa_last_corner].y,
326
seg_w, mask, style->line.color, opa);
327
328
lv_draw_aa_ver_seg(main_line->p2.x + pattern[aa_last_corner].x + 1, main_line->p2.y + pattern[aa_last_corner].y,
329
-seg_w, mask, style->line.color, opa);
330
}
331
aa_last_corner = i;
332
}
333
} else {
334
if(pattern[i - 1].y != pattern[i].y) {
335
lv_coord_t seg_w = pattern[i].x - pattern[aa_last_corner].x;
336
if(main_line->sx < 0) {
337
lv_draw_aa_hor_seg(main_line->p1.x + pattern[aa_last_corner].x + seg_w + 1, main_line->p1.y + pattern[aa_last_corner].y - 1,
338
seg_w, mask, style->line.color, opa);
339
340
lv_draw_aa_hor_seg(main_line->p2.x + pattern[aa_last_corner].x + seg_w + 1, main_line->p2.y + pattern[aa_last_corner].y + 1,
341
-seg_w, mask, style->line.color, opa);
342
} else {
343
lv_draw_aa_hor_seg(main_line->p1.x + pattern[aa_last_corner].x, main_line->p1.y + pattern[aa_last_corner].y - 1,
344
seg_w, mask, style->line.color, opa);
345
346
lv_draw_aa_hor_seg(main_line->p2.x + pattern[aa_last_corner].x, main_line->p2.y + pattern[aa_last_corner].y + 1,
347
-seg_w, mask, style->line.color, opa);
348
}
349
aa_last_corner = i;
350
}
351
}
352
353
}
354
#endif
355
}
356
357
358
359
#if LV_ANTIALIAS
360
/*Add the last part of anti-aliasing for the perpendicular ending*/
361
if(width != 0) { /*Due to rounding error with very thin lines it looks ugly*/
362
if(main_line->hor) {
363
lv_coord_t seg_w = pattern[width_safe - 1].y - pattern[aa_last_corner].y;
364
if(main_line->sy < 0) {
365
lv_draw_aa_ver_seg(main_line->p1.x + pattern[aa_last_corner].x - 1, main_line->p1.y + pattern[aa_last_corner].y + seg_w,
366
seg_w + main_line->sy, mask, style->line.color, opa);
367
368
lv_draw_aa_ver_seg(main_line->p2.x + pattern[aa_last_corner].x + 1, main_line->p2.y + pattern[aa_last_corner].y + seg_w,
369
-(seg_w + main_line->sy), mask, style->line.color, opa);
370
371
} else {
372
lv_draw_aa_ver_seg(main_line->p1.x + pattern[aa_last_corner].x - 1, main_line->p1.y + pattern[aa_last_corner].y,
373
seg_w + main_line->sy, mask, style->line.color, opa);
374
375
lv_draw_aa_ver_seg(main_line->p2.x + pattern[aa_last_corner].x + 1, main_line->p2.y + pattern[aa_last_corner].y,
376
-(seg_w + main_line->sy), mask, style->line.color, opa);
377
}
378
} else {
379
lv_coord_t seg_w = pattern[width_safe - 1].x - pattern[aa_last_corner].x;
380
if(main_line->sx < 0) {
381
lv_draw_aa_hor_seg(main_line->p1.x + pattern[aa_last_corner].x + seg_w, main_line->p1.y + pattern[aa_last_corner].y - 1,
382
seg_w + main_line->sx, mask, style->line.color, opa);
383
384
lv_draw_aa_hor_seg(main_line->p2.x + pattern[aa_last_corner].x + seg_w, main_line->p2.y + pattern[aa_last_corner].y + 1,
385
-(seg_w + main_line->sx), mask, style->line.color, opa);
386
387
} else {
388
lv_draw_aa_hor_seg(main_line->p1.x + pattern[aa_last_corner].x, main_line->p1.y + pattern[aa_last_corner].y - 1,
389
seg_w + main_line->sx, mask, style->line.color, opa);
390
391
lv_draw_aa_hor_seg(main_line->p2.x + pattern[aa_last_corner].x, main_line->p2.y + pattern[aa_last_corner].y + 1,
392
-(seg_w + main_line->sx), mask, style->line.color, opa);
393
}
394
395
}
396
}
397
#endif
398
399
#if LV_ANTIALIAS
400
401
/*Shift the anti aliasing on the edges (-1, 1 or 0 (zero only in case width == 0))*/
402
lv_coord_t aa_shift1;
403
lv_coord_t aa_shift2;
404
405
if(main_line->hor == false) {
406
if(main_line->sx < 0) {
407
aa_shift1 = -1;
408
aa_shift2 = width == 0 ? 0 : aa_shift1;
409
} else {
410
aa_shift2 = 1;
411
aa_shift1 = width == 0 ? 0 : aa_shift2;
412
}
413
} else {
414
if(main_line->sy < 0) {
415
aa_shift1 = -1;
416
aa_shift2 = width == 0 ? 0 : aa_shift1;
417
} else {
418
aa_shift2 = 1;
419
aa_shift1 = width == 0 ? 0 : aa_shift2;
420
}
421
}
422
423
#endif
424
425
volatile lv_point_t prev_p;
426
prev_p.x = main_line->p1.x;
427
prev_p.y = main_line->p1.y;
428
lv_area_t draw_area;
429
bool first_run = true;
430
431
if(main_line->hor) {
432
while(line_next_y(main_line)) {
433
for(i = 0; i < width; i++) {
434
draw_area.x1 = prev_p.x + pattern[i].x;
435
draw_area.y1 = prev_p.y + pattern[i].y;
436
draw_area.x2 = draw_area.x1 + main_line->p_act.x - prev_p.x - 1;
437
draw_area.y2 = draw_area.y1;
438
fill_fp(&draw_area, mask, style->line.color, opa);
439
440
/* Fill the gaps
441
* When stepping in y one pixel remains empty on every corner (don't do this on the first segment ) */
442
if(i != 0 && pattern[i].x != pattern[i - 1].x && !first_run) {
443
px_fp(draw_area.x1, draw_area.y1 - main_line->sy, mask, style->line.color, opa);
444
}
445
}
446
447
#if LV_ANTIALIAS
448
lv_draw_aa_hor_seg(prev_p.x + pattern[0].x, prev_p.y + pattern[0].y - aa_shift1,
449
-(main_line->p_act.x - prev_p.x), mask, style->line.color, opa);
450
lv_draw_aa_hor_seg(prev_p.x + pattern[width_safe - 1].x, prev_p.y + pattern[width_safe - 1].y + aa_shift2,
451
main_line->p_act.x - prev_p.x, mask, style->line.color, opa);
452
#endif
453
454
first_run = false;
455
456
prev_p.x = main_line->p_act.x;
457
prev_p.y = main_line->p_act.y;
458
}
459
460
for(i = 0; i < width; i++) {
461
draw_area.x1 = prev_p.x + pattern[i].x;
462
draw_area.y1 = prev_p.y + pattern[i].y;
463
draw_area.x2 = draw_area.x1 + main_line->p_act.x - prev_p.x;
464
draw_area.y2 = draw_area.y1;
465
fill_fp(&draw_area, mask, style->line.color, opa);
466
467
/* Fill the gaps
468
* When stepping in y one pixel remains empty on every corner */
469
if(i != 0 && pattern[i].x != pattern[i - 1].x && !first_run) {
470
px_fp(draw_area.x1, draw_area.y1 - main_line->sy, mask, style->line.color, opa);
471
}
472
}
473
474
#if LV_ANTIALIAS
475
lv_draw_aa_hor_seg(prev_p.x + pattern[0].x, prev_p.y + pattern[0].y - aa_shift1,
476
-(main_line->p_act.x - prev_p.x + 1), mask, style->line.color, opa);
477
lv_draw_aa_hor_seg(prev_p.x + pattern[width_safe - 1].x, prev_p.y + pattern[width_safe - 1].y + aa_shift2,
478
main_line->p_act.x - prev_p.x + 1, mask, style->line.color, opa);
479
#endif
480
}
481
/*Rather a vertical line*/
482
else {
483
484
while(line_next_x(main_line)) {
485
for(i = 0; i < width; i++) {
486
draw_area.x1 = prev_p.x + pattern[i].x;
487
draw_area.y1 = prev_p.y + pattern[i].y;
488
draw_area.x2 = draw_area.x1;
489
draw_area.y2 = draw_area.y1 + main_line->p_act.y - prev_p.y - 1;
490
491
fill_fp(&draw_area, mask, style->line.color, opa);
492
493
/* Fill the gaps
494
* When stepping in x one pixel remains empty on every corner (don't do this on the first segment ) */
495
if(i != 0 && pattern[i].y != pattern[i - 1].y && !first_run) {
496
px_fp(draw_area.x1 - main_line->sx, draw_area.y1, mask, style->line.color, opa);
497
}
498
499
}
500
501
#if LV_ANTIALIAS
502
lv_draw_aa_ver_seg(prev_p.x + pattern[0].x - aa_shift1, prev_p.y + pattern[0].y,
503
-(main_line->p_act.y - prev_p.y), mask, style->line.color, opa);
504
lv_draw_aa_ver_seg(prev_p.x + pattern[width_safe - 1].x + aa_shift2, prev_p.y + pattern[width_safe - 1].y,
505
main_line->p_act.y - prev_p.y, mask, style->line.color, opa);
506
#endif
507
508
first_run = false;
509
510
prev_p.x = main_line->p_act.x;
511
prev_p.y = main_line->p_act.y;
512
}
513
514
/*Draw the last part*/
515
for(i = 0; i < width; i++) {
516
draw_area.x1 = prev_p.x + pattern[i].x;
517
draw_area.y1 = prev_p.y + pattern[i].y;
518
draw_area.x2 = draw_area.x1;
519
draw_area.y2 = draw_area.y1 + main_line->p_act.y - prev_p.y;
520
521
fill_fp(&draw_area, mask, style->line.color, opa);
522
523
/* Fill the gaps
524
* When stepping in x one pixel remains empty on every corner */
525
if(i != 0 && pattern[i].y != pattern[i - 1].y && !first_run) {
526
px_fp(draw_area.x1 - main_line->sx, draw_area.y1, mask, style->line.color, opa);
527
}
528
}
529
530
#if LV_ANTIALIAS
531
lv_draw_aa_ver_seg(prev_p.x + pattern[0].x - aa_shift1, prev_p.y + pattern[0].y,
532
-(main_line->p_act.y - prev_p.y + 1), mask, style->line.color, opa);
533
lv_draw_aa_ver_seg(prev_p.x + pattern[width_safe - 1].x + aa_shift2, prev_p.y + pattern[width_safe - 1].y,
534
main_line->p_act.y - prev_p.y + 1, mask, style->line.color, opa);
535
#endif
536
}
537
}
538
539
540
static void line_init(line_draw_t * line, const lv_point_t * p1, const lv_point_t * p2)
541
{
542
line->p1.x = p1->x;
543
line->p1.y = p1->y;
544
line->p2.x = p2->x;
545
line->p2.y = p2->y;
546
547
line->dx = LV_MATH_ABS(line->p2.x - line->p1.x);
548
line->sx = line->p1.x < line->p2.x ? 1 : -1;
549
line->dy = LV_MATH_ABS(line->p2.y - line->p1.y);
550
line->sy = line->p1.y < line->p2.y ? 1 : -1;
551
line->err = (line->dx > line->dy ? line->dx : -line->dy) / 2;
552
line->e2 = 0;
553
line->hor = line->dx > line->dy ? true : false; /*Rather horizontal or vertical*/
554
555
line->p_act.x = line->p1.x;
556
line->p_act.y = line->p1.y;
557
}
558
559
static bool line_next(line_draw_t * line)
560
{
561
if(line->p_act.x == line->p2.x && line->p_act.y == line->p2.y) return false;
562
line->e2 = line->err;
563
if(line->e2 > -line->dx) {
564
line->err -= line->dy;
565
line->p_act.x += line->sx;
566
}
567
if(line->e2 < line->dy) {
568
line->err += line->dx;
569
line->p_act.y += line->sy;
570
}
571
return true;
572
}
573
574
/**
575
* Iterate until step one in y direction.
576
* @param line
577
* @return
578
*/
579
static bool line_next_y(line_draw_t * line)
580
{
581
lv_coord_t last_y = line->p_act.y;
582
583
do {
584
if(!line_next(line)) return false;
585
} while(last_y == line->p_act.y);
586
587
return true;
588
589
}
590
591
/**
592
* Iterate until step one in x direction.
593
* @param line
594
* @return
595
*/
596
static bool line_next_x(line_draw_t * line)
597
{
598
lv_coord_t last_x = line->p_act.x;
599
600
do {
601
if(!line_next(line)) return false;
602
} while(last_x == line->p_act.x);
603
604
return true;
605
606
}
607
608
609