4
4
#include "shared-module/displayio/area.h"
5
5
6
6
#include "py/runtime.h"
7
+ #include "py/gc.h"
8
+
7
9
#include "stdlib.h"
8
10
#include <stdio.h>
9
11
12
14
// #define VECTORIO_POLYGON_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__)
13
15
14
16
17
+ // Converts a list of points tuples to a flat list of ints for speedier internal use.
18
+ // Also validates the points.
19
+ static void _clobber_points_list (vectorio_polygon_t * self , mp_obj_t points_tuple_list ) {
20
+ size_t len = 0 ;
21
+ mp_obj_t * items ;
22
+ mp_obj_list_get (points_tuple_list , & len , & items );
23
+ VECTORIO_POLYGON_DEBUG ("polygon_points_list len: %d\n" , len );
24
+
25
+ if ( len < 3 ) {
26
+ mp_raise_TypeError_varg (translate ("Polygon needs at least 3 points" ));
27
+ }
28
+
29
+ if ( self -> len < 2 * len ) {
30
+ if ( self -> points_list != NULL ) {
31
+ gc_free ( self -> points_list );
32
+ }
33
+ self -> points_list = gc_alloc ( 2 * len * sizeof (int ), false, false );
34
+ }
35
+ self -> len = 2 * len ;
36
+
37
+ for ( size_t i = 0 ; i < len ; ++ i ) {
38
+ size_t tuple_len = 0 ;
39
+ mp_obj_t * tuple_items ;
40
+ mp_obj_tuple_get (items [i ], & tuple_len , & tuple_items );
41
+
42
+ if (tuple_len != 2 ) {
43
+ mp_raise_ValueError_varg (translate ("%q must be a tuple of length 2" ), MP_QSTR_point );
44
+ }
45
+ if (!mp_obj_get_int_maybe (tuple_items [0 ], & self -> points_list [2 * i ])) {
46
+ self -> len = 0 ;
47
+ gc_free ( self -> points_list );
48
+ self -> points_list = NULL ;
49
+ mp_raise_ValueError_varg (translate ("unsupported %q type" ), MP_QSTR_point );
50
+ }
51
+ if (!mp_obj_get_int_maybe (tuple_items [1 ], & self -> points_list [2 * i + 1 ])) {
52
+ self -> len = 0 ;
53
+ gc_free ( self -> points_list );
54
+ self -> points_list = NULL ;
55
+ mp_raise_ValueError_varg (translate ("unsupported %q type" ), MP_QSTR_point );
56
+ }
57
+ }
58
+ }
59
+
60
+
61
+
15
62
void common_hal_vectorio_polygon_construct (vectorio_polygon_t * self , mp_obj_t points_list ) {
16
63
VECTORIO_POLYGON_DEBUG ("%p polygon_construct\n" , self );
17
- self -> points_list = points_list ;
64
+ self -> points_list = NULL ;
65
+ self -> len = 0 ;
18
66
self -> on_dirty .obj = NULL ;
67
+ _clobber_points_list ( self , points_list );
19
68
}
20
69
21
70
22
71
mp_obj_t common_hal_vectorio_polygon_get_points (vectorio_polygon_t * self ) {
23
72
return self -> points_list ;
24
73
}
25
74
void common_hal_vectorio_polygon_set_points (vectorio_polygon_t * self , mp_obj_t points_list ) {
26
- self -> points_list = points_list ;
75
+ _clobber_points_list ( self , points_list ) ;
27
76
if (self -> on_dirty .obj != NULL ) {
28
77
self -> on_dirty .event (self -> on_dirty .obj );
29
78
}
@@ -38,21 +87,16 @@ void common_hal_vectorio_polygon_set_on_dirty(vectorio_polygon_t *self, vectorio
38
87
39
88
40
89
void common_hal_vectorio_polygon_get_area (void * polygon , displayio_area_t * area ) {
41
- VECTORIO_POLYGON_DEBUG ("%p polygon get_area" , polygon );
42
90
vectorio_polygon_t * self = polygon ;
43
- size_t len ;
44
- mp_obj_t * points ;
45
- mp_obj_list_get (self -> points_list , & len , & points );
46
- VECTORIO_POLYGON_DEBUG (" len: %2d, points: %d\n" , len , len /2 );
47
91
48
92
area -> x1 = SHRT_MAX ;
49
93
area -> y1 = SHRT_MAX ;
50
94
area -> x2 = SHRT_MIN ;
51
95
area -> y2 = SHRT_MIN ;
52
- for (size_t i = 0 ; i < len ; ++ i ) {
53
- mp_int_t x = mp_obj_get_int ( points [i ]) ;
96
+ for (size_t i = 0 ; i < self -> len ; ++ i ) {
97
+ int x = self -> points_list [i ];
54
98
++ i ;
55
- mp_int_t y = mp_obj_get_int ( points [i ]) ;
99
+ int y = self -> points_list [i ];
56
100
if (x <= area -> x1 ) area -> x1 = x - 1 ;
57
101
if (y <= area -> y1 ) area -> y1 = y - 1 ;
58
102
if (x >= area -> x2 ) area -> x2 = x + 1 ;
@@ -73,22 +117,19 @@ __attribute__((always_inline)) static inline int line_side( mp_int_t x1, mp_int_
73
117
uint32_t common_hal_vectorio_polygon_get_pixel (void * obj , int16_t x , int16_t y ) {
74
118
VECTORIO_POLYGON_DEBUG ("%p polygon get_pixel %d, %d\n" , obj , x , y );
75
119
vectorio_polygon_t * self = obj ;
76
- size_t len ;
77
- mp_obj_t * points ;
78
- mp_obj_list_get (self -> points_list , & len , & points );
79
120
80
- if (len == 0 ) {
121
+ if (self -> len == 0 ) {
81
122
return 0 ;
82
123
}
83
124
84
125
int winding_number = 0 ;
85
- mp_int_t x1 = mp_obj_get_int ( points [0 ]) ;
86
- mp_int_t y1 = mp_obj_get_int ( points [1 ]) ;
87
- for (size_t i = 2 ; i <= len + 1 ; ++ i ) {
126
+ int x1 = self -> points_list [0 ];
127
+ int y1 = self -> points_list [1 ];
128
+ for (size_t i = 2 ; i <= self -> len + 1 ; ++ i ) {
88
129
VECTORIO_POLYGON_DEBUG (" {(%3d, %3d)," , x1 , y1 );
89
- mp_int_t x2 = mp_obj_get_int ( points [i % len ]) ;
130
+ int x2 = self -> points_list [i % self -> len ];
90
131
++ i ;
91
- mp_int_t y2 = mp_obj_get_int ( points [i % len ]) ;
132
+ int y2 = self -> points_list [i % self -> len ];
92
133
VECTORIO_POLYGON_DEBUG (" (%3d, %3d)}\n" , x2 , y2 );
93
134
if ( y1 <= y ) {
94
135
if ( y2 > y && line_side (x1 , y1 , x2 , y2 , x , y ) > 0 ) {
0 commit comments