44#include "shared-module/displayio/area.h"
55
66#include "py/runtime.h"
7+ #include "py/gc.h"
8+
79#include "stdlib.h"
810#include <stdio.h>
911
1214// #define VECTORIO_POLYGON_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__)
1315
1416
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+
1562void common_hal_vectorio_polygon_construct (vectorio_polygon_t * self , mp_obj_t points_list ) {
1663 VECTORIO_POLYGON_DEBUG ("%p polygon_construct\n" , self );
17- self -> points_list = points_list ;
64+ self -> points_list = NULL ;
65+ self -> len = 0 ;
1866 self -> on_dirty .obj = NULL ;
67+ _clobber_points_list ( self , points_list );
1968}
2069
2170
2271mp_obj_t common_hal_vectorio_polygon_get_points (vectorio_polygon_t * self ) {
2372 return self -> points_list ;
2473}
2574void 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 ) ;
2776 if (self -> on_dirty .obj != NULL ) {
2877 self -> on_dirty .event (self -> on_dirty .obj );
2978 }
@@ -38,21 +87,16 @@ void common_hal_vectorio_polygon_set_on_dirty(vectorio_polygon_t *self, vectorio
3887
3988
4089void common_hal_vectorio_polygon_get_area (void * polygon , displayio_area_t * area ) {
41- VECTORIO_POLYGON_DEBUG ("%p polygon get_area" , polygon );
4290 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 );
4791
4892 area -> x1 = SHRT_MAX ;
4993 area -> y1 = SHRT_MAX ;
5094 area -> x2 = SHRT_MIN ;
5195 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 ];
5498 ++ i ;
55- mp_int_t y = mp_obj_get_int ( points [i ]) ;
99+ int y = self -> points_list [i ];
56100 if (x <= area -> x1 ) area -> x1 = x - 1 ;
57101 if (y <= area -> y1 ) area -> y1 = y - 1 ;
58102 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_
73117uint32_t common_hal_vectorio_polygon_get_pixel (void * obj , int16_t x , int16_t y ) {
74118 VECTORIO_POLYGON_DEBUG ("%p polygon get_pixel %d, %d\n" , obj , x , y );
75119 vectorio_polygon_t * self = obj ;
76- size_t len ;
77- mp_obj_t * points ;
78- mp_obj_list_get (self -> points_list , & len , & points );
79120
80- if (len == 0 ) {
121+ if (self -> len == 0 ) {
81122 return 0 ;
82123 }
83124
84125 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 ) {
88129 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 ];
90131 ++ i ;
91- mp_int_t y2 = mp_obj_get_int ( points [i % len ]) ;
132+ int y2 = self -> points_list [i % self -> len ];
92133 VECTORIO_POLYGON_DEBUG (" (%3d, %3d)}\n" , x2 , y2 );
93134 if ( y1 <= y ) {
94135 if ( y2 > y && line_side (x1 , y1 , x2 , y2 , x , y ) > 0 ) {
0 commit comments