PicoVector: Rewrite around new linked-lists poly.

pull/1019/head
Phil Howard 2024-07-22 17:33:52 +01:00 zatwierdzone przez Phil Howard
rodzic faf675c9f8
commit 1115900443
7 zmienionych plików z 236 dodań i 123 usunięć

Wyświetl plik

@ -151,11 +151,28 @@ namespace pimoroni {
uint8_t *pdest = &((uint8_t *)frame_buffer)[tile->x + ((tile->y + y) * bounds.w)];
for(int x = 0; x < tile->w; x++) {
uint8_t alpha = *palpha;
uint8_t dest = *pdest;
// TODO: Try to alpha blend RGB332... somewhat?
if(alpha == 0) {
} else {
if(alpha == 255) {
*pdest = color;
}else if(alpha == 0) {
}else{
// blend tha pixel
uint16_t sr = (color & 0b11100000) >> 5;
uint16_t sg = (color & 0b00011100) >> 2;
uint16_t sb = (color & 0b00000011);
uint16_t dr = (dest & 0b11100000) >> 5;
uint16_t dg = (dest & 0b00011100) >> 2;
uint16_t db = (dest & 0b00000011);
uint8_t r = ((sr * alpha) + (dr * (255 - alpha))) >> 8;
uint8_t g = ((sg * alpha) + (dg * (255 - alpha))) >> 8;
uint8_t b = ((sb * alpha) + (db * (255 - alpha))) >> 8;
// recombine the channels
*pdest = (r << 5) | (g << 2) | (b);
}
pdest++;

Wyświetl plik

@ -107,20 +107,20 @@ namespace pimoroni {
}else if(alpha == 0) {
}else{
// blend tha pixel
uint16_t sr = (color & 0b1111100000000000) >> 11;
uint16_t sg = (color & 0b0000011111100000) >> 5;
uint16_t sb = (color & 0b0000000000011111);
uint16_t sr = (__builtin_bswap16(color) & 0b1111100000000000) >> 11;
uint16_t sg = (__builtin_bswap16(color) & 0b0000011111100000) >> 5;
uint16_t sb = (__builtin_bswap16(color) & 0b0000000000011111);
uint16_t dr = (dest & 0b1111100000000000) >> 11;
uint16_t dg = (dest & 0b0000011111100000) >> 5;
uint16_t db = (dest & 0b0000000000011111);
uint16_t dr = (__builtin_bswap16(dest) & 0b1111100000000000) >> 11;
uint16_t dg = (__builtin_bswap16(dest) & 0b0000011111100000) >> 5;
uint16_t db = (__builtin_bswap16(dest) & 0b0000000000011111);
uint8_t r = ((sr * alpha) + (dr * (255 - alpha))) >> 8;
uint8_t g = ((sg * alpha) + (dg * (255 - alpha))) >> 8;
uint8_t b = ((sb * alpha) + (db * (255 - alpha))) >> 8;
// recombine the channels
*pdest = (r << 11) | (g << 5) | (b);
*pdest = __builtin_bswap16((r << 11) | (g << 5) | (b));
}
pdest++;

Wyświetl plik

@ -216,27 +216,20 @@ af_glyph_t *find_glyph(af_face_t *face, char c) {
void af_render_glyph(af_glyph_t* glyph, af_text_metrics_t *tm) {
assert(glyph != NULL);
pp_poly_t poly;
poly.count = glyph->path_count;
poly.paths = (pp_path_t *)AF_MALLOC(poly.count * sizeof(pp_path_t));
for(uint32_t i = 0; i < poly.count; i++) {
pp_path_t *path = &poly.paths[i];
path->count = glyph->paths[i].point_count;
path->points = (pp_point_t *)AF_MALLOC(glyph->paths[i].point_count * sizeof(pp_point_t));
for(uint32_t j = 0; j < path->count; j++) {
pp_point_t *point = &path->points[j];
point->x = glyph->paths[i].points[j].x;
point->y = glyph->paths[i].points[j].y;
pp_poly_t *poly = pp_poly_new();
for(uint32_t i = 0; i < glyph->path_count; i++) {
pp_path_t *path = pp_poly_add_path(poly);
for(uint32_t j = 0; j < glyph->paths[i].point_count; j++) {
pp_path_add_point(path, {
glyph->paths[i].points[j].x,
glyph->paths[i].points[j].y
});
}
}
pp_render(&poly);
pp_render(poly);
for(uint32_t i = 0; i < poly.count; i++) {
pp_path_t *path = &poly.paths[i];
AF_FREE(path->points);
}
AF_FREE(poly.paths);
pp_poly_free(poly);
}
void af_render_character(af_face_t *face, const char c, af_text_metrics_t *tm) {

Wyświetl plik

@ -31,7 +31,7 @@ namespace pimoroni {
}
void PicoVector::transform(pp_path_t *path, pp_mat3_t *t) {
for (auto j = 0u; j < path->count; j++) {
for (auto j = 0; j < path->count; j++) {
path->points[j] = pp_point_transform(&path->points[j], t);
}
}
@ -51,8 +51,10 @@ namespace pimoroni {
}
void PicoVector::transform(pp_poly_t *poly, pp_mat3_t *t) {
for (auto i = 0u; i < poly->count; i++) {
transform(&poly->paths[i], t);
pp_path_t *path = poly->paths;
while(path) {
transform(path, t);
path = path->next;
}
}

Wyświetl plik

@ -109,13 +109,19 @@ namespace pimoroni {
void draw(pp_poly_t *poly, pp_mat3_t *t);
void draw(pp_path_t *path) {
pp_poly_t poly = {.paths = path, .count = 1};
draw(&poly);
pp_poly_t *poly = pp_poly_new();
poly->paths = path;
draw(poly);
poly->paths = NULL; // Don't free our non-owned path
pp_poly_free(poly);
};
void draw(pp_path_t *path, pp_mat3_t *t) {
pp_poly_t poly = {.paths = path, .count = 1};
draw(&poly, t);
pp_poly_t *poly = pp_poly_new();
poly->paths = path;
draw(poly, t);
poly->paths = NULL; // Don't free our non-owned path
pp_poly_free(poly);
};
static constexpr size_t pretty_poly_buffer_size() {

Wyświetl plik

@ -100,15 +100,26 @@ typedef struct {
uint8_t *data;
} pp_tile_t;
typedef struct {
typedef struct _pp_path_t {
pp_point_t *points;
uint32_t count;
int count; // number of points currently stored in points buffer
int storage; // size of *points buffer
struct _pp_path_t *next; // next path in the linked list
} pp_path_t;
void pp_path_add_point(pp_path_t *path, pp_point_t p);
void pp_path_add_points(pp_path_t *path, pp_point_t *p, int count);
void pp_path_add_path(pp_path_t *path, pp_path_t *other);
pp_rect_t pp_path_bounds(const pp_path_t *c);
typedef struct {
pp_path_t *paths;
uint32_t count;
pp_path_t *paths;
} pp_poly_t;
pp_poly_t *pp_poly_new();
void pp_poly_free(pp_poly_t *poly);
pp_path_t* pp_poly_tail_path(pp_poly_t *p);
pp_path_t* pp_poly_add_path(pp_poly_t *p);
pp_rect_t pp_poly_bounds(pp_poly_t *p);
int pp_poly_path_count(pp_poly_t *p);
// user settings
typedef void (*pp_tile_callback_t)(const pp_tile_t *tile);
@ -124,8 +135,6 @@ void pp_antialias(pp_antialias_t antialias);
pp_mat3_t *pp_transform(pp_mat3_t *transform);
void pp_render(pp_poly_t *polygon);
pp_rect_t pp_contour_bounds(const pp_path_t *c);
pp_rect_t pp_polygon_bounds(pp_poly_t *p);
#ifdef __cplusplus
}
@ -249,25 +258,102 @@ uint8_t pp_tile_get(const pp_tile_t *tile, const int32_t x, const int32_t y) {
return tile->data[(x - tile->x) + (y - tile->y) * PP_TILE_BUFFER_SIZE];
}
pp_poly_t *pp_poly_new() {
pp_poly_t *poly = (pp_poly_t *)PP_MALLOC(sizeof(pp_poly_t));
poly->paths = NULL;
return poly;
}
void pp_poly_free(pp_poly_t *poly) {
if(poly->paths) {
pp_path_t *path = poly->paths;
while(path) {
PP_FREE(path->points);
pp_path_t *free_path = path;
path = path->next;
PP_FREE(free_path);
}
}
PP_FREE(poly);
}
// polygon and path implementation
pp_path_t* pp_poly_tail_path(pp_poly_t *poly) {
pp_path_t *path = poly->paths;
while(path->next) path = path->next;
return path;
}
int pp_poly_path_count(pp_poly_t *poly) {
if(!poly->paths) return 0;
pp_path_t *path = poly->paths;
int i = 0;
while(path->next) {
i++;
path = path->next;
}
return i;
}
pp_path_t* pp_poly_add_path(pp_poly_t *poly) {
pp_path_t *path = (pp_path_t *)PP_MALLOC(sizeof(pp_path_t));
memset(path, 0, sizeof(pp_path_t));
path->storage = 8;
path->points = (pp_point_t *)PP_MALLOC(sizeof(pp_point_t) * path->storage);
if(!poly->paths) {
poly->paths = path;
}else{
pp_path_t *tail = pp_poly_tail_path(poly);
tail->next = path;
}
return path;
}
pp_point_t* pp_path_tail_point(pp_path_t *path) {
return (path->count > 0) ? &path->points[path->count -1] : NULL;
}
void pp_path_add_point(pp_path_t *path, pp_point_t p) {
if(path->count == path->storage) { // no storage left, double buffer size
path->points = (pp_point_t *)PP_REALLOC(path->points, sizeof(pp_point_t) * (path->storage * 2));
path->storage *= 2;
}
path->points[path->count] = p;
path->count++;
}
void pp_path_add_points(pp_path_t *path, pp_point_t *points, int count) {
if(count + path->count > path->storage) { // not enough storage, allocate
path->points = (pp_point_t *)PP_REALLOC(path->points, sizeof(pp_point_t) * (count + path->count));
path->storage = count + path->count;
}
memcpy(&path->points[count], points, sizeof(pp_point_t) * count);
path->count += count;
}
// pp_contour_t implementation
pp_rect_t pp_contour_bounds(const pp_path_t *c) {
int minx = c->points[0].x, maxx = minx;
int miny = c->points[0].y, maxy = miny;
for(uint32_t i = 1; i < c->count; i++) {
minx = _pp_min(minx, c->points[i].x);
miny = _pp_min(miny, c->points[i].y);
maxx = _pp_max(maxx, c->points[i].x);
maxy = _pp_max(maxy, c->points[i].y);
}
return (pp_rect_t){.x = minx, .y = miny, .w = maxx - minx, .h = maxy - miny};
pp_rect_t pp_path_bounds(const pp_path_t *path) {
int minx = INT_MAX, maxx = -INT_MAX, miny = INT_MAX, maxy = -INT_MAX;
for(int i = 0; i < path->count; i++) {
minx = _pp_min(minx, path->points[i].x);
miny = _pp_min(miny, path->points[i].y);
maxx = _pp_max(maxx, path->points[i].x);
maxy = _pp_max(maxy, path->points[i].y);
}
return (pp_rect_t){minx, miny, maxx - minx, maxy - miny};
}
pp_rect_t pp_polygon_bounds(pp_poly_t *p) {
if(p->count == 0) {return (pp_rect_t){};}
pp_rect_t b = pp_contour_bounds(&p->paths[0]);
for(uint32_t i = 1; i < p->count; i++) {
pp_rect_t cb = pp_contour_bounds(&p->paths[i]);
pp_path_t *path = p->paths;
if(!path) return (pp_rect_t){};
pp_rect_t b = pp_path_bounds(path);
path = path->next;
while(path) {
pp_rect_t cb = pp_path_bounds(path);
b = pp_rect_merge(&b, &cb);
path = path->next;
}
return b;
}
@ -391,30 +477,24 @@ void add_line_segment_to_nodes(const pp_point_t start, const pp_point_t end) {
//#endif
}
void build_nodes(pp_path_t *contour, pp_rect_t *bounds) {
void build_nodes(pp_path_t *path, pp_rect_t *tb) {
PP_COORD_TYPE aa_scale = (PP_COORD_TYPE)(1 << _pp_antialias);
pp_point_t tile_origin = (pp_point_t) {
.x = bounds->x * aa_scale,
.y = bounds->y * aa_scale
};
pp_point_t tile_origin = (pp_point_t){tb->x * aa_scale, tb->y * aa_scale};
// start with the last point to close the loop, transform it, scale for antialiasing, and offset to tile origin
pp_point_t last = contour->points[contour->count - 1];
pp_point_t last = path->points[path->count - 1];
if(_pp_transform) last = pp_point_transform(&last, _pp_transform);
last.x *= aa_scale; last.y *= aa_scale;
last = pp_point_sub(&last, &tile_origin);
for(uint32_t i = 0; i < contour->count; i++) {
// fetch next point, transform it, scale for antialiasing, and offset to tile origin
pp_point_t point = contour->points[i];
if(_pp_transform) point = pp_point_transform(&point, _pp_transform);
point.x *= aa_scale; point.y *= aa_scale;
point = pp_point_sub(&point, &tile_origin);
add_line_segment_to_nodes(last, point);
last = point;
for(int i = 0; i < path->count; i++) {
pp_point_t next = path->points[i];
if(_pp_transform) next = pp_point_transform(&next, _pp_transform);
next.x *= aa_scale; next.y *= aa_scale;
next = pp_point_sub(&next, &tile_origin);
add_line_segment_to_nodes(last, next);
last = next;
}
}
@ -497,20 +577,18 @@ pp_rect_t render_nodes(pp_rect_t *tb) {
void pp_render(pp_poly_t *polygon) {
debug("> draw polygon with %u contours\n", polygon->count);
debug("> draw polygon with %u contours\n", pp_poly_path_count(polygon));
if(polygon->count == 0) {
return;
}
if(!polygon->paths) return;
// determine extreme bounds
pp_rect_t polygon_bounds = pp_polygon_bounds(polygon);
pp_rect_t pb = pp_polygon_bounds(polygon);
if(_pp_transform) {
polygon_bounds = pp_rect_transform(&polygon_bounds, _pp_transform);
pb = pp_rect_transform(&pb, _pp_transform);
}
debug(" - polygon bounds %d, %d (%d x %d)\n", polygon_bounds.x, polygon_bounds.y, polygon_bounds.w, polygon_bounds.h);
debug(" - polygon bounds %d, %d (%d x %d)\n", pb.x, pb.y, pb.w, pb.h);
debug(" - clip %d, %d (%d x %d)\n", _pp_clip.x, _pp_clip.y, _pp_clip.w, _pp_clip.h);
#ifdef USE_RP2040_INTERP
@ -526,8 +604,8 @@ void pp_render(pp_poly_t *polygon) {
// iterate over tiles
debug(" - processing tiles\n");
for(int32_t y = polygon_bounds.y; y < polygon_bounds.y + polygon_bounds.h; y += PP_TILE_BUFFER_SIZE) {
for(int32_t x = polygon_bounds.x; x < polygon_bounds.x + polygon_bounds.w; x += PP_TILE_BUFFER_SIZE) {
for(int32_t y = pb.y; y < pb.y + pb.h; y += PP_TILE_BUFFER_SIZE) {
for(int32_t x = pb.x; x < pb.x + pb.w; x += PP_TILE_BUFFER_SIZE) {
pp_rect_t tb = (pp_rect_t){.x = x, .y = y, .w = PP_TILE_BUFFER_SIZE, .h = PP_TILE_BUFFER_SIZE};
tb = pp_rect_intersection(&tb, &_pp_clip);
debug(" : %d, %d (%d x %d)\n", tb.x, tb.y, tb.w, tb.h);
@ -540,11 +618,13 @@ void pp_render(pp_poly_t *polygon) {
memset(tile_buffer, 0, PP_TILE_BUFFER_SIZE * PP_TILE_BUFFER_SIZE);
// build the nodes for each pp_path_t
for(uint32_t i = 0; i < polygon->count; i++) {
pp_path_t pp_path_t = polygon->paths[i];
debug(" : build nodes for path\n");
build_nodes(&pp_path_t, &tb);
}
pp_path_t *path = polygon->paths;
if(!path) return;
do {
debug(" : build nodes for path (%d points)\n", path->count);
build_nodes(path, &tb);
path = path->next;
} while(path);
debug(" : render the tile\n");
// render the tile

Wyświetl plik

@ -27,7 +27,7 @@ typedef struct _VECTOR_obj_t {
typedef struct _PATH_obj_t {
mp_obj_base_t base;
pp_path_t path;
pp_path_t *path;
} _PATH_obj_t;
void __printf_debug_flush() {
@ -170,19 +170,19 @@ mp_obj_t RECTANGLE_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_k
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
_PATH_obj_t *self = mp_obj_malloc_with_finaliser(_PATH_obj_t, &POLYGON_type);
self->path = (pp_path_t *)PP_MALLOC(sizeof(pp_path_t));
self->path->storage = 4;
self->path->points = (pp_point_t *)PP_MALLOC(sizeof(pp_point_t) * self->path->storage);
picovector_point_type x = mp_picovector_get_point_type(args[ARG_x].u_obj);
picovector_point_type y = mp_picovector_get_point_type(args[ARG_y].u_obj);
picovector_point_type w = mp_picovector_get_point_type(args[ARG_w].u_obj);
picovector_point_type h = mp_picovector_get_point_type(args[ARG_h].u_obj);
self->path.points = m_new(pp_point_t, 4);
self->path.count = 4;
self->path.points[0] = {picovector_point_type(x), picovector_point_type(y)};
self->path.points[1] = {picovector_point_type(x + w), picovector_point_type(y)};
self->path.points[2] = {picovector_point_type(x + w), picovector_point_type(y + h)};
self->path.points[3] = {picovector_point_type(x), picovector_point_type(y + h)};
pp_path_add_point(self->path, {picovector_point_type(x), picovector_point_type(y)});
pp_path_add_point(self->path, {picovector_point_type(x + w), picovector_point_type(y)});
pp_path_add_point(self->path, {picovector_point_type(x + w), picovector_point_type(y + h)});
pp_path_add_point(self->path, {picovector_point_type(x), picovector_point_type(y + h)});
return self;
}
@ -215,15 +215,17 @@ mp_obj_t REGULAR_POLYGON_make_new(const mp_obj_type_t *type, size_t n_args, size
float angle = (360.0f / sides) * (M_PI / 180.0f);
self->path.points = m_new(pp_point_t, sides);
self->path.count = sides;
self->path = (pp_path_t *)PP_MALLOC(sizeof(pp_path_t));
self->path->storage = sides;
self->path->points = (pp_point_t *)PP_MALLOC(sizeof(pp_point_t) * self->path->storage);
for(auto s = 0u; s < sides; s++) {
float current_angle = angle * s + rotation;
self->path.points[s] = {
pp_path_add_point(self->path, {
(picovector_point_type)(cos(current_angle) * radius) + o_x,
(picovector_point_type)(sin(current_angle) * radius) + o_y
};
});
}
return self;
@ -235,10 +237,11 @@ mp_obj_t POLYGON_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
size_t num_points = n_args;
const mp_obj_t *points = all_args;
if(num_points < 3) mp_raise_ValueError("Polygon: At least 3 points required.");
self->path = (pp_path_t *)PP_MALLOC(sizeof(pp_path_t));
self->path->storage = num_points;
self->path->points = (pp_point_t *)PP_MALLOC(sizeof(pp_point_t) * self->path->storage);
self->path.points = m_new(pp_point_t, num_points);
self->path.count = num_points;
if(num_points < 3) mp_raise_ValueError("Polygon: At least 3 points required.");
for(auto i = 0u; i < num_points; i++) {
mp_obj_t c_obj = points[i];
@ -249,10 +252,10 @@ mp_obj_t POLYGON_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
if(t_point->len != 2) mp_raise_ValueError("Tuple must have X, Y");
self->path.points[i] = {
pp_path_add_point(self->path, {
(picovector_point_type)mp_picovector_get_point_type(t_point->items[0]),
(picovector_point_type)mp_picovector_get_point_type(t_point->items[1]),
};
});
}
return self;
@ -264,13 +267,13 @@ mp_obj_t POLYGON_centroid(mp_obj_t self_in) {
PP_COORD_TYPE sum_x = (PP_COORD_TYPE)0;
PP_COORD_TYPE sum_y = (PP_COORD_TYPE)0;
for(auto i = 0u; i < self->path.count; i++) {
sum_x += self->path.points[i].x;
sum_y += self->path.points[i].y;
for(auto i = 0; i < self->path->count; i++) {
sum_x += self->path->points[i].x;
sum_y += self->path->points[i].y;
}
sum_x /= (float)self->path.count;
sum_y /= (float)self->path.count;
sum_x /= (float)self->path->count;
sum_y /= (float)self->path->count;
mp_obj_t tuple[2];
tuple[0] = mp_picovector_set_point_type((int)(sum_x));
@ -282,7 +285,7 @@ mp_obj_t POLYGON_centroid(mp_obj_t self_in) {
mp_obj_t POLYGON_bounds(mp_obj_t self_in) {
_PATH_obj_t *self = MP_OBJ_TO_PTR2(self_in, _PATH_obj_t);
pp_rect_t bounds = pp_contour_bounds(&self->path);
pp_rect_t bounds = pp_path_bounds(self->path);
mp_obj_t tuple[4];
tuple[0] = mp_picovector_set_point_type((int)(bounds.x));
@ -297,10 +300,10 @@ void POLYGON_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t ki
(void)kind;
_PATH_obj_t *self = MP_OBJ_TO_PTR2(self_in, _PATH_obj_t);
pp_rect_t bounds = pp_contour_bounds(&self->path);
pp_rect_t bounds = pp_path_bounds(self->path);
mp_print_str(print, "Polygon(points = ");
mp_obj_print_helper(print, mp_picovector_set_point_type(self->path.count), PRINT_REPR);
mp_obj_print_helper(print, mp_picovector_set_point_type(self->path->count), PRINT_REPR);
mp_print_str(print, ", bounds = ");
mp_obj_print_helper(print, mp_picovector_set_point_type(bounds.x), PRINT_REPR);
mp_print_str(print, ", ");
@ -314,7 +317,8 @@ void POLYGON_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t ki
mp_obj_t POLYGON__del__(mp_obj_t self_in) {
_PATH_obj_t *self = MP_OBJ_TO_PTR2(self_in, _PATH_obj_t);
(void)self;
PP_FREE(self->path->points);
PP_FREE(self->path);
// TODO: Do we actually need to free anything here, if it's on GC heap it should get collected
return mp_const_none;
}
@ -323,7 +327,7 @@ typedef struct _mp_obj_polygon_it_t {
mp_obj_base_t base;
mp_fun_1_t iternext;
mp_obj_t polygon;
size_t cur;
int cur;
} mp_obj_polygon_it_t;
static mp_obj_t py_path_it_iternext(mp_obj_t self_in) {
@ -332,11 +336,11 @@ static mp_obj_t py_path_it_iternext(mp_obj_t self_in) {
//mp_printf(&mp_plat_print, "points: %d, current: %d\n", polygon->contour.count, self->cur);
if(self->cur >= path->path.count) return MP_OBJ_STOP_ITERATION;
if(self->cur >= path->path->count) return MP_OBJ_STOP_ITERATION;
mp_obj_t tuple[2];
tuple[0] = mp_picovector_set_point_type((int)(path->path.points[self->cur].x));
tuple[1] = mp_picovector_set_point_type((int)(path->path.points[self->cur].y));
tuple[0] = mp_picovector_set_point_type((int)(path->path->points[self->cur].x));
tuple[1] = mp_picovector_set_point_type((int)(path->path->points[self->cur].y));
self->cur++;
return mp_obj_new_tuple(2, tuple);
@ -484,7 +488,7 @@ mp_obj_t VECTOR_rotate(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_arg
float angle = mp_obj_get_float(args[ARG_angle].u_obj);
self->vector->rotate(&poly->path, origin, angle);
self->vector->rotate(poly->path, origin, angle);
return mp_const_none;
}
@ -509,7 +513,7 @@ mp_obj_t VECTOR_translate(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_
pp_point_t translate = {(PP_COORD_TYPE)args[ARG_x].u_int, (PP_COORD_TYPE)args[ARG_y].u_int};
self->vector->translate(&poly->path, translate);
self->vector->translate(poly->path, translate);
return mp_const_none;
}
@ -521,23 +525,34 @@ mp_obj_t VECTOR_draw(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
_VECTOR_obj_t *self = MP_OBJ_TO_PTR2(pos_args[0], _VECTOR_obj_t);
pp_poly_t group;
group.count = num_polygons;
group.paths = (pp_path_t *)m_new(pp_path_t, num_polygons);
if(num_polygons == 1) {
mp_obj_t poly_obj = polygons[0];
if(!MP_OBJ_IS_TYPE(poly_obj, &POLYGON_type)) mp_raise_TypeError("draw: Polygon required.");
_PATH_obj_t *poly = MP_OBJ_TO_PTR2(poly_obj, _PATH_obj_t);
self->vector->draw(poly->path);
return mp_const_none;
}
pp_poly_t *group = pp_poly_new();
for(auto i = 0u; i < num_polygons; i++) {
pp_path_t *path = pp_poly_add_path(group);
mp_obj_t poly_obj = polygons[i];
if(!MP_OBJ_IS_TYPE(poly_obj, &POLYGON_type)) mp_raise_TypeError("draw: Polygon required.");
_PATH_obj_t *poly = MP_OBJ_TO_PTR2(poly_obj, _PATH_obj_t);
group.paths[i].points = poly->path.points;
group.paths[i].count = poly->path.count;
pp_path_add_points(path, poly->path->points, poly->path->count);
}
self->vector->draw(&group);
self->vector->draw(group);
m_free(group.paths);
pp_poly_free(group);
return mp_const_none;
}