Skip to content

Commit b9e478a

Browse files
authored
Merge pull request #7471 from matemaciek/main
Add function for drawing polygons to bitmaptools
2 parents 0ca6cc7 + 812fa2b commit b9e478a

File tree

4 files changed

+184
-27
lines changed

4 files changed

+184
-27
lines changed

locale/circuitpython.pot

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

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

shared-bindings/bitmaptools/__init__.c

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

526+
//| def draw_polygon(
527+
//| dest_bitmap: displayio.Bitmap,
528+
//| xs: ReadableBuffer,
529+
//| ys: ReadableBuffer,
530+
//| value: int,
531+
//| close: Optional[bool] = True,
532+
//| ) -> None:
533+
//| """Draw a polygon conecting points on provided bitmap with provided value
534+
//|
535+
//| :param bitmap dest_bitmap: Destination bitmap that will be written into
536+
//| :param ReadableBuffer xs: x-pixel position of the polygon's vertices
537+
//| :param ReadableBuffer ys: y-pixel position of the polygon's vertices
538+
//| :param int value: Bitmap palette index that will be written into the
539+
//| line in the destination bitmap
540+
//| :param bool close: (Optional) Wether to connect first and last point. (True)
541+
//|
542+
//| .. code-block:: Python
543+
//|
544+
//| import board
545+
//| import displayio
546+
//| import bitmaptools
547+
//|
548+
//| display = board.DISPLAY
549+
//| main_group = displayio.Group()
550+
//| display.root_group = main_group
551+
//|
552+
//| palette = displayio.Palette(3)
553+
//| palette[0] = 0xffffff
554+
//| palette[1] = 0x0000ff
555+
//| palette[2] = 0xff0000
556+
//|
557+
//| bmp = displayio.Bitmap(128,128, 3)
558+
//| bmp.fill(0)
559+
//|
560+
//| xs = bytes([4, 101, 101, 19])
561+
//| ys = bytes([4, 19, 121, 101])
562+
//| bitmaptools.draw_polygon(bmp, xs, ys, 1)
563+
//|
564+
//| xs = bytes([14, 60, 110])
565+
//| ys = bytes([14, 24, 90])
566+
//| bitmaptools.draw_polygon(bmp, xs, ys, 2)
567+
//|
568+
//| tilegrid = displayio.TileGrid(bitmap=bmp, pixel_shader=palette)
569+
//| main_group.append(tilegrid)
570+
//|
571+
//| while True:
572+
//| pass
573+
//| """
574+
//| ...
575+
//|
576+
STATIC mp_obj_t bitmaptools_obj_draw_polygon(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
577+
enum {ARG_dest_bitmap, ARG_xs, ARG_ys, ARG_value, ARG_close};
578+
579+
static const mp_arg_t allowed_args[] = {
580+
{MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
581+
{MP_QSTR_xs, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
582+
{MP_QSTR_ys, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
583+
{MP_QSTR_value, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL}},
584+
{MP_QSTR_close, MP_ARG_BOOL, {.u_bool = true}},
585+
};
586+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
587+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
588+
589+
displayio_bitmap_t *destination = MP_OBJ_TO_PTR(args[ARG_dest_bitmap].u_obj); // the destination bitmap
590+
591+
mp_buffer_info_t xs_buf, ys_buf;
592+
mp_get_buffer_raise(args[ARG_xs].u_obj, &xs_buf, MP_BUFFER_READ);
593+
mp_get_buffer_raise(args[ARG_ys].u_obj, &ys_buf, MP_BUFFER_READ);
594+
size_t xs_size = mp_binary_get_size('@', xs_buf.typecode, NULL);
595+
size_t ys_size = mp_binary_get_size('@', ys_buf.typecode, NULL);
596+
size_t xs_len = xs_buf.len / xs_size;
597+
size_t ys_len = ys_buf.len / ys_size;
598+
if (xs_size != ys_size) {
599+
mp_raise_ValueError(translate("Coordinate arrays types have different sizes"));
600+
}
601+
if (xs_len != ys_len) {
602+
mp_raise_ValueError(translate("Coordinate arrays have different lengths"));
603+
}
604+
605+
uint32_t value, color_depth;
606+
value = args[ARG_value].u_int;
607+
color_depth = (1 << destination->bits_per_value);
608+
if (color_depth <= value) {
609+
mp_raise_ValueError(translate("out of range of target"));
610+
}
611+
612+
bool close = args[ARG_close].u_bool;
613+
614+
common_hal_bitmaptools_draw_polygon(destination, xs_buf.buf, ys_buf.buf, xs_len, xs_size, value, close);
615+
616+
return mp_const_none;
617+
}
618+
619+
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_polygon_obj, 0, bitmaptools_obj_draw_polygon);
620+
526621
//| def arrayblit(
527622
//| bitmap: displayio.Bitmap,
528623
//| data: ReadableBuffer,
@@ -784,6 +879,7 @@ STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = {
784879
{ MP_ROM_QSTR(MP_QSTR_fill_region), MP_ROM_PTR(&bitmaptools_fill_region_obj) },
785880
{ MP_ROM_QSTR(MP_QSTR_boundary_fill), MP_ROM_PTR(&bitmaptools_boundary_fill_obj) },
786881
{ MP_ROM_QSTR(MP_QSTR_draw_line), MP_ROM_PTR(&bitmaptools_draw_line_obj) },
882+
{ MP_ROM_QSTR(MP_QSTR_draw_polygon), MP_ROM_PTR(&bitmaptools_draw_polygon_obj) },
787883
{ MP_ROM_QSTR(MP_QSTR_dither), MP_ROM_PTR(&bitmaptools_dither_obj) },
788884
{ MP_ROM_QSTR(MP_QSTR_DitherAlgorithm), MP_ROM_PTR(&bitmaptools_dither_algorithm_type) },
789885
};

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)