Merge pull request #7471 from matemaciek/main

Add function for drawing polygons to bitmaptools
This commit is contained in:
MicroDev 2023-03-07 08:28:07 +05:30 committed by GitHub
commit b9e478af39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 184 additions and 27 deletions

View File

@ -813,6 +813,14 @@ msgid ""
"connection."
msgstr ""
#: shared-bindings/bitmaptools/__init__.c
msgid "Coordinate arrays have different lengths"
msgstr ""
#: shared-bindings/bitmaptools/__init__.c
msgid "Coordinate arrays types have different sizes"
msgstr ""
#: py/persistentcode.c
msgid "Corrupt .mpy file"
msgstr ""

View File

@ -523,6 +523,101 @@ STATIC mp_obj_t bitmaptools_obj_draw_line(size_t n_args, const mp_obj_t *pos_arg
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_line_obj, 0, bitmaptools_obj_draw_line);
// requires all 6 arguments
//| def draw_polygon(
//| dest_bitmap: displayio.Bitmap,
//| xs: ReadableBuffer,
//| ys: ReadableBuffer,
//| value: int,
//| close: Optional[bool] = True,
//| ) -> None:
//| """Draw a polygon conecting points on provided bitmap with provided value
//|
//| :param bitmap dest_bitmap: Destination bitmap that will be written into
//| :param ReadableBuffer xs: x-pixel position of the polygon's vertices
//| :param ReadableBuffer ys: y-pixel position of the polygon's vertices
//| :param int value: Bitmap palette index that will be written into the
//| line in the destination bitmap
//| :param bool close: (Optional) Wether to connect first and last point. (True)
//|
//| .. code-block:: Python
//|
//| import board
//| import displayio
//| import bitmaptools
//|
//| display = board.DISPLAY
//| main_group = displayio.Group()
//| display.root_group = main_group
//|
//| palette = displayio.Palette(3)
//| palette[0] = 0xffffff
//| palette[1] = 0x0000ff
//| palette[2] = 0xff0000
//|
//| bmp = displayio.Bitmap(128,128, 3)
//| bmp.fill(0)
//|
//| xs = bytes([4, 101, 101, 19])
//| ys = bytes([4, 19, 121, 101])
//| bitmaptools.draw_polygon(bmp, xs, ys, 1)
//|
//| xs = bytes([14, 60, 110])
//| ys = bytes([14, 24, 90])
//| bitmaptools.draw_polygon(bmp, xs, ys, 2)
//|
//| tilegrid = displayio.TileGrid(bitmap=bmp, pixel_shader=palette)
//| main_group.append(tilegrid)
//|
//| while True:
//| pass
//| """
//| ...
//|
STATIC mp_obj_t bitmaptools_obj_draw_polygon(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum {ARG_dest_bitmap, ARG_xs, ARG_ys, ARG_value, ARG_close};
static const mp_arg_t allowed_args[] = {
{MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
{MP_QSTR_xs, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
{MP_QSTR_ys, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
{MP_QSTR_value, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL}},
{MP_QSTR_close, MP_ARG_BOOL, {.u_bool = true}},
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
displayio_bitmap_t *destination = MP_OBJ_TO_PTR(args[ARG_dest_bitmap].u_obj); // the destination bitmap
mp_buffer_info_t xs_buf, ys_buf;
mp_get_buffer_raise(args[ARG_xs].u_obj, &xs_buf, MP_BUFFER_READ);
mp_get_buffer_raise(args[ARG_ys].u_obj, &ys_buf, MP_BUFFER_READ);
size_t xs_size = mp_binary_get_size('@', xs_buf.typecode, NULL);
size_t ys_size = mp_binary_get_size('@', ys_buf.typecode, NULL);
size_t xs_len = xs_buf.len / xs_size;
size_t ys_len = ys_buf.len / ys_size;
if (xs_size != ys_size) {
mp_raise_ValueError(translate("Coordinate arrays types have different sizes"));
}
if (xs_len != ys_len) {
mp_raise_ValueError(translate("Coordinate arrays have different lengths"));
}
uint32_t value, color_depth;
value = args[ARG_value].u_int;
color_depth = (1 << destination->bits_per_value);
if (color_depth <= value) {
mp_raise_ValueError(translate("out of range of target"));
}
bool close = args[ARG_close].u_bool;
common_hal_bitmaptools_draw_polygon(destination, xs_buf.buf, ys_buf.buf, xs_len, xs_size, value, close);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_polygon_obj, 0, bitmaptools_obj_draw_polygon);
//| def arrayblit(
//| bitmap: displayio.Bitmap,
//| data: ReadableBuffer,
@ -784,6 +879,7 @@ STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_fill_region), MP_ROM_PTR(&bitmaptools_fill_region_obj) },
{ MP_ROM_QSTR(MP_QSTR_boundary_fill), MP_ROM_PTR(&bitmaptools_boundary_fill_obj) },
{ MP_ROM_QSTR(MP_QSTR_draw_line), MP_ROM_PTR(&bitmaptools_draw_line_obj) },
{ MP_ROM_QSTR(MP_QSTR_draw_polygon), MP_ROM_PTR(&bitmaptools_draw_polygon_obj) },
{ MP_ROM_QSTR(MP_QSTR_dither), MP_ROM_PTR(&bitmaptools_dither_obj) },
{ MP_ROM_QSTR(MP_QSTR_DitherAlgorithm), MP_ROM_PTR(&bitmaptools_dither_algorithm_type) },
};

View File

@ -64,6 +64,7 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
int16_t x1, int16_t y1,
uint32_t value);
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);
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);
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);
void common_hal_bitmaptools_dither(displayio_bitmap_t *dest_bitmap, displayio_bitmap_t *source_bitmap, displayio_colorspace_t colorspace, bitmaptools_dither_algorithm_t algorithm);

View File

@ -384,37 +384,11 @@ void common_hal_bitmaptools_boundary_fill(displayio_bitmap_t *destination,
}
void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
STATIC void draw_line(displayio_bitmap_t *destination,
int16_t x0, int16_t y0,
int16_t x1, int16_t y1,
uint32_t value) {
//
// adapted from Adafruit_CircuitPython_Display_Shapes.Polygon._line
//
// update the dirty rectangle
int16_t xbb0, xbb1, ybb0, ybb1;
if (x0 < x1) {
xbb0 = x0;
xbb1 = x1 + 1;
} else {
xbb0 = x1;
xbb1 = x0 + 1;
}
if (y0 < y1) {
ybb0 = y0;
ybb1 = y1 + 1;
} else {
ybb0 = y1;
ybb1 = y0 + 1;
}
displayio_area_t area = { xbb0, ybb0, xbb1, ybb1, NULL };
displayio_area_t bitmap_area = { 0, 0, destination->width, destination->height, NULL };
displayio_area_compute_overlap(&area, &bitmap_area, &area);
displayio_bitmap_set_dirty_area(destination, &area);
int16_t temp, x, y;
if (x0 == x1) { // vertical line
@ -488,6 +462,84 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
}
}
void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
int16_t x0, int16_t y0,
int16_t x1, int16_t y1,
uint32_t value) {
//
// adapted from Adafruit_CircuitPython_Display_Shapes.Polygon._line
//
// update the dirty rectangle
int16_t xbb0, xbb1, ybb0, ybb1;
if (x0 < x1) {
xbb0 = x0;
xbb1 = x1 + 1;
} else {
xbb0 = x1;
xbb1 = x0 + 1;
}
if (y0 < y1) {
ybb0 = y0;
ybb1 = y1 + 1;
} else {
ybb0 = y1;
ybb1 = y0 + 1;
}
displayio_area_t area = { xbb0, ybb0, xbb1, ybb1, NULL };
displayio_area_t bitmap_area = { 0, 0, destination->width, destination->height, NULL };
displayio_area_compute_overlap(&area, &bitmap_area, &area);
displayio_bitmap_set_dirty_area(destination, &area);
draw_line(destination, x0, y0, x1, y1, value);
}
STATIC int32_t ith(void *data, size_t i, int element_size) {
switch (element_size) {
default:
case 1:
return *((int8_t *)data + i);
case 2:
return *((int16_t *)data + i);
case 4:
return *((int32_t *)data + i);
}
}
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) {
int16_t x0, y0, xmin, xmax, ymin, ymax, xprev, yprev, x, y;
x0 = ith(xs, 0, point_size);
xmin = x0;
xmax = x0;
xprev = x0;
y0 = ith(ys, 0, point_size);
ymin = y0;
ymax = y0;
yprev = y0;
for (size_t i = 1; i < points_len; i++) {
x = ith(xs, i, point_size);
y = ith(ys, i, point_size);
draw_line(destination, xprev, yprev, x, y, value);
xprev = x;
yprev = y;
xmin = MIN(xmin, x);
xmax = MAX(xmax, x);
ymin = MIN(ymin, y);
ymax = MAX(ymax, y);
}
if (close) {
draw_line(destination, xprev, yprev, x0, y0, value);
}
displayio_area_t area = { xmin, ymin, xmax, ymax, NULL };
displayio_area_t bitmap_area = { 0, 0, destination->width, destination->height, NULL };
displayio_area_compute_overlap(&area, &bitmap_area, &area);
displayio_bitmap_set_dirty_area(destination, &area);
}
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) {
uint32_t mask = (1 << common_hal_displayio_bitmap_get_bits_per_value(self)) - 1;