Skip to content

Commit e474df3

Browse files
committed
Add function for drawing polygons to bitmaptools
1 parent 2276254 commit e474df3

File tree

4 files changed

+152
-27
lines changed

4 files changed

+152
-27
lines changed

locale/circuitpython.pot

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,14 @@ msgid ""
814814
"connection."
815815
msgstr ""
816816

817+
#: shared-bindings/bitmaptools/__init__.c
818+
msgid "Coordinate arrays have different lengths"
819+
msgstr ""
820+
821+
#: shared-bindings/bitmaptools/__init__.c
822+
msgid "Coordinate arrays types have different sizes"
823+
msgstr ""
824+
817825
#: py/persistentcode.c
818826
msgid "Corrupt .mpy file"
819827
msgstr ""

shared-bindings/bitmaptools/__init__.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,69 @@ STATIC mp_obj_t bitmaptools_obj_draw_line(size_t n_args, const mp_obj_t *pos_arg
522522
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_line_obj, 0, bitmaptools_obj_draw_line);
523523
// requires all 6 arguments
524524

525+
//| def draw_polygon(
526+
//| dest_bitmap: displayio.Bitmap,
527+
//| xs: ReadableBuffer,
528+
//| ys: ReadableBuffer,
529+
//| value: int,
530+
//| close: Optional[bool] = True,
531+
//| ) -> None:
532+
//| """Draw a polygon conecting points on provided bitmap with provided value
533+
//|
534+
//| :param bitmap dest_bitmap: Destination bitmap that will be written into
535+
//| :param int xs: x-pixel position of the polygon's vertices
536+
//| :param int ys: y-pixel position of the polygon's vertices
537+
//| :param int value: Bitmap palette index that will be written into the
538+
//| line in the destination bitmap
539+
//| :param bool close: (Optional) Wether to connect first and last point. (True)
540+
//| """
541+
//| ...
542+
//|
543+
STATIC mp_obj_t bitmaptools_obj_draw_polygon(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
544+
enum {ARG_dest_bitmap, ARG_xs, ARG_ys, ARG_value, ARG_close};
545+
546+
static const mp_arg_t allowed_args[] = {
547+
{MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
548+
{MP_QSTR_xs, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
549+
{MP_QSTR_ys, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
550+
{MP_QSTR_value, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL}},
551+
{MP_QSTR_close, MP_ARG_BOOL, {.u_bool = true}},
552+
};
553+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
554+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
555+
556+
displayio_bitmap_t *destination = MP_OBJ_TO_PTR(args[ARG_dest_bitmap].u_obj); // the destination bitmap
557+
558+
mp_buffer_info_t xs_buf, ys_buf;
559+
mp_get_buffer_raise(args[ARG_xs].u_obj, &xs_buf, MP_BUFFER_READ);
560+
mp_get_buffer_raise(args[ARG_ys].u_obj, &ys_buf, MP_BUFFER_READ);
561+
size_t xs_size = mp_binary_get_size('@', xs_buf.typecode, NULL);
562+
size_t ys_size = mp_binary_get_size('@', ys_buf.typecode, NULL);
563+
size_t xs_len = xs_buf.len / xs_size;
564+
size_t ys_len = ys_buf.len / ys_size;
565+
if (xs_size != ys_size) {
566+
mp_raise_ValueError(translate("Coordinate arrays types have different sizes"));
567+
}
568+
if (xs_len != ys_len) {
569+
mp_raise_ValueError(translate("Coordinate arrays have different lengths"));
570+
}
571+
572+
uint32_t value, color_depth;
573+
value = args[ARG_value].u_int;
574+
color_depth = (1 << destination->bits_per_value);
575+
if (color_depth <= value) {
576+
mp_raise_ValueError(translate("out of range of target"));
577+
}
578+
579+
bool close = args[ARG_close].u_bool;
580+
581+
common_hal_bitmaptools_draw_polygon(destination, xs_buf.buf, ys_buf.buf, xs_len, xs_size, value, close);
582+
583+
return mp_const_none;
584+
}
585+
586+
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_polygon_obj, 0, bitmaptools_obj_draw_polygon);
587+
525588
//| def arrayblit(
526589
//| bitmap: displayio.Bitmap,
527590
//| data: ReadableBuffer,
@@ -783,6 +846,7 @@ STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = {
783846
{ MP_ROM_QSTR(MP_QSTR_fill_region), MP_ROM_PTR(&bitmaptools_fill_region_obj) },
784847
{ MP_ROM_QSTR(MP_QSTR_boundary_fill), MP_ROM_PTR(&bitmaptools_boundary_fill_obj) },
785848
{ MP_ROM_QSTR(MP_QSTR_draw_line), MP_ROM_PTR(&bitmaptools_draw_line_obj) },
849+
{ MP_ROM_QSTR(MP_QSTR_draw_polygon), MP_ROM_PTR(&bitmaptools_draw_polygon_obj) },
786850
{ MP_ROM_QSTR(MP_QSTR_dither), MP_ROM_PTR(&bitmaptools_dither_obj) },
787851
{ MP_ROM_QSTR(MP_QSTR_DitherAlgorithm), MP_ROM_PTR(&bitmaptools_dither_algorithm_type) },
788852
};

shared-bindings/bitmaptools/__init__.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
6464
int16_t x1, int16_t y1,
6565
uint32_t value);
6666

67+
void common_hal_bitmaptools_draw_polygon(displayio_bitmap_t *destination, void *xs, void *ys, size_t points_len, int point_size, uint32_t value, bool close);
6768
void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, mp_obj_t *file, int element_size, int bits_per_pixel, bool reverse_pixels_in_word, bool swap_bytes, bool reverse_rows);
6869
void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int element_size, int x1, int y1, int x2, int y2, bool skip_specified, uint32_t skip_index);
6970
void common_hal_bitmaptools_dither(displayio_bitmap_t *dest_bitmap, displayio_bitmap_t *source_bitmap, displayio_colorspace_t colorspace, bitmaptools_dither_algorithm_t algorithm);

shared-module/bitmaptools/__init__.c

Lines changed: 79 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -384,37 +384,11 @@ void common_hal_bitmaptools_boundary_fill(displayio_bitmap_t *destination,
384384

385385
}
386386

387-
void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
387+
STATIC void draw_line(displayio_bitmap_t *destination,
388388
int16_t x0, int16_t y0,
389389
int16_t x1, int16_t y1,
390390
uint32_t value) {
391391

392-
//
393-
// adapted from Adafruit_CircuitPython_Display_Shapes.Polygon._line
394-
//
395-
396-
// update the dirty rectangle
397-
int16_t xbb0, xbb1, ybb0, ybb1;
398-
if (x0 < x1) {
399-
xbb0 = x0;
400-
xbb1 = x1 + 1;
401-
} else {
402-
xbb0 = x1;
403-
xbb1 = x0 + 1;
404-
}
405-
if (y0 < y1) {
406-
ybb0 = y0;
407-
ybb1 = y1 + 1;
408-
} else {
409-
ybb0 = y1;
410-
ybb1 = y0 + 1;
411-
}
412-
displayio_area_t area = { xbb0, ybb0, xbb1, ybb1, NULL };
413-
displayio_area_t bitmap_area = { 0, 0, destination->width, destination->height, NULL };
414-
displayio_area_compute_overlap(&area, &bitmap_area, &area);
415-
416-
displayio_bitmap_set_dirty_area(destination, &area);
417-
418392
int16_t temp, x, y;
419393

420394
if (x0 == x1) { // vertical line
@@ -488,6 +462,84 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
488462
}
489463
}
490464

465+
void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
466+
int16_t x0, int16_t y0,
467+
int16_t x1, int16_t y1,
468+
uint32_t value) {
469+
470+
//
471+
// adapted from Adafruit_CircuitPython_Display_Shapes.Polygon._line
472+
//
473+
474+
// update the dirty rectangle
475+
int16_t xbb0, xbb1, ybb0, ybb1;
476+
if (x0 < x1) {
477+
xbb0 = x0;
478+
xbb1 = x1 + 1;
479+
} else {
480+
xbb0 = x1;
481+
xbb1 = x0 + 1;
482+
}
483+
if (y0 < y1) {
484+
ybb0 = y0;
485+
ybb1 = y1 + 1;
486+
} else {
487+
ybb0 = y1;
488+
ybb1 = y0 + 1;
489+
}
490+
displayio_area_t area = { xbb0, ybb0, xbb1, ybb1, NULL };
491+
displayio_area_t bitmap_area = { 0, 0, destination->width, destination->height, NULL };
492+
displayio_area_compute_overlap(&area, &bitmap_area, &area);
493+
494+
displayio_bitmap_set_dirty_area(destination, &area);
495+
496+
draw_line(destination, x0, y0, x1, y1, value);
497+
}
498+
499+
STATIC int32_t ith(void *data, size_t i, int element_size) {
500+
switch (element_size) {
501+
default:
502+
case 1:
503+
return *((int8_t *)data + i);
504+
case 2:
505+
return *((int16_t *)data + i);
506+
case 4:
507+
return *((int32_t *)data + i);
508+
}
509+
}
510+
511+
void common_hal_bitmaptools_draw_polygon(displayio_bitmap_t *destination, void *xs, void *ys, size_t points_len, int point_size, uint32_t value, bool close) {
512+
int16_t x0, y0, xmin, xmax, ymin, ymax, xprev, yprev, x, y;
513+
x0 = ith(xs, 0, point_size);
514+
xmin = x0;
515+
xmax = x0;
516+
xprev = x0;
517+
y0 = ith(ys, 0, point_size);
518+
ymin = y0;
519+
ymax = y0;
520+
yprev = y0;
521+
522+
for (size_t i = 1; i < points_len; i++) {
523+
x = ith(xs, i, point_size);
524+
y = ith(ys, i, point_size);
525+
draw_line(destination, xprev, yprev, x, y, value);
526+
xprev = x;
527+
yprev = y;
528+
xmin = MIN(xmin, x);
529+
xmax = MAX(xmax, x);
530+
ymin = MIN(ymin, y);
531+
ymax = MAX(ymax, y);
532+
}
533+
if (close) {
534+
draw_line(destination, xprev, yprev, x0, y0, value);
535+
}
536+
537+
displayio_area_t area = { xmin, ymin, xmax, ymax, NULL };
538+
displayio_area_t bitmap_area = { 0, 0, destination->width, destination->height, NULL };
539+
displayio_area_compute_overlap(&area, &bitmap_area, &area);
540+
displayio_bitmap_set_dirty_area(destination, &area);
541+
}
542+
491543
void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int element_size, int x1, int y1, int x2, int y2, bool skip_specified, uint32_t skip_value) {
492544
uint32_t mask = (1 << common_hal_displayio_bitmap_get_bits_per_value(self)) - 1;
493545

0 commit comments

Comments
 (0)