displayio.Bitmap: Allow modification though the buffer protocol
It is required to call .dirty() with appropriate arguments after modifications through the buffer protocol, or the display might not be updated correctly.
This commit is contained in:
parent
a78d00a73d
commit
78089107bc
@ -397,8 +397,7 @@ STATIC mp_obj_t bitmaptools_arrayblit(size_t n_args, const mp_obj_t *pos_args, m
|
||||
{ MP_QSTR_x2, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_y2, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_skip_index, MP_ARG_OBJ, {.u_obj = mp_const_none } },
|
||||
}
|
||||
;
|
||||
};
|
||||
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);
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "shared-bindings/displayio/Bitmap.h"
|
||||
#include "shared-module/displayio/Bitmap.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@ -43,8 +44,13 @@
|
||||
//| per row is a multiple of 4, then the resulting memoryview will correspond directly with the bitmap's contents. Otherwise,
|
||||
//| the bitmap data is packed into the memoryview with unspecified padding.
|
||||
//|
|
||||
//| A read-only buffer can be used e.g., with ``ulab.numpy.frombuffer`` to efficiently create an array with the same content as a Bitmap;
|
||||
//| to move data efficiently from ulab back into a Bitmap, use `bitmaptools.arrayblit`.
|
||||
//| A Bitmap can be treated as a buffer, allowing its content to be
|
||||
//| viewed and modified using e.g., with ``ulab.numpy.frombuffer``,
|
||||
//| but the `displayio.Bitmap.dirty` method must be used to inform
|
||||
//| displayio when a bitmap was modified through the buffer interface.
|
||||
//|
|
||||
//| `bitmaptools.arrayblit` can also be useful to omve data efficiently
|
||||
//| into a Bitmap.
|
||||
//| """
|
||||
//|
|
||||
//| def __init__(self, width: int, height: int, value_count: int) -> None:
|
||||
@ -299,11 +305,57 @@ STATIC mp_obj_t displayio_bitmap_obj_fill(mp_obj_t self_in, mp_obj_t value_obj)
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(displayio_bitmap_fill_obj, displayio_bitmap_obj_fill);
|
||||
|
||||
//| def dirty(self, x1: int=0, y1: int=0, x2: int=-1, y2:int = -1) -> None:
|
||||
//| """Inform displayio of bitmap updates done via the buffer
|
||||
//| protocol.
|
||||
//|
|
||||
//| :param int x1: Minimum x-value for rectangular bounding box to be considered as modified
|
||||
//| :param int y1: Minimum y-value for rectangular bounding box to be considered as modified
|
||||
//| :param int x2: Maximum x-value (exclusive) for rectangular bounding box to be considered as modified
|
||||
//| :param int y2: Maximum y-value (exclusive) for rectangular bounding box to be considered as modified
|
||||
//|
|
||||
//| If x1 or y1 are not specified, they are taken as 0. If x2 or y2
|
||||
//| are not specified, or are given as -1, they are taken as the width
|
||||
//| and height of the image. Thus, calling dirty() with the
|
||||
//| default arguments treats the whole bitmap as modified.
|
||||
//|
|
||||
//| When a bitmap is modified through the buffer protocol, the
|
||||
//| display will not be properly updated unless the bitmap is
|
||||
//| notified of the "dirty rectangle" that encloses all modified
|
||||
//| pixels."""
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t displayio_bitmap_obj_dirty(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
displayio_bitmap_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
enum { ARG_x1, ARG_y1, ARG_x2, ARG_y2 };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_x1, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_y1, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_x2, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_y2, MP_ARG_INT, {.u_int = -1} },
|
||||
};
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
displayio_area_t dirty_area = {
|
||||
.x1 = args[ARG_x1].u_int,
|
||||
.y1 = args[ARG_y1].u_int,
|
||||
.x2 = args[ARG_x2].u_int == -1 ? self->width : args[ARG_x2].u_int,
|
||||
.y2 = args[ARG_y2].u_int == -1 ? self->height : args[ARG_y2].u_int,
|
||||
};
|
||||
|
||||
displayio_bitmap_set_dirty_area(self, &dirty_area);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(displayio_bitmap_dirty_obj, 0, displayio_bitmap_obj_dirty);
|
||||
|
||||
STATIC const mp_rom_map_elem_t displayio_bitmap_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&displayio_bitmap_height_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&displayio_bitmap_width_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(&displayio_bitmap_blit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&displayio_bitmap_fill_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_dirty), MP_ROM_PTR(&displayio_bitmap_dirty_obj) },
|
||||
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(displayio_bitmap_locals_dict, displayio_bitmap_locals_dict_table);
|
||||
|
@ -236,7 +236,7 @@ void common_hal_displayio_bitmap_fill(displayio_bitmap_t *self, uint32_t value)
|
||||
}
|
||||
|
||||
int common_hal_displayio_bitmap_get_buffer(displayio_bitmap_t *self, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
|
||||
if (flags & MP_BUFFER_WRITE) {
|
||||
if ((flags & MP_BUFFER_WRITE) && self->read_only) {
|
||||
return 1;
|
||||
}
|
||||
bufinfo->len = self->stride * self->height * sizeof(size_t);
|
||||
|
Loading…
Reference in New Issue
Block a user