Merge pull request #8136 from FoamyGuy/blit_skip_self_index
adding skip_self_index argument to bitmap.blit()
This commit is contained in:
commit
3ec9f8a118
@ -949,6 +949,132 @@ STATIC mp_obj_t bitmaptools_obj_draw_circle(size_t n_args, const mp_obj_t *pos_a
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_circle_obj, 0, bitmaptools_obj_draw_circle);
|
||||
|
||||
//| def blit(
|
||||
//| dest_bitmap: displayio.Bitmap,
|
||||
//| source_bitmap: displayio.Bitmap,
|
||||
//| x: int,
|
||||
//| y: int,
|
||||
//| *,
|
||||
//| x1: int,
|
||||
//| y1: int,
|
||||
//| x2: int,
|
||||
//| y2: int,
|
||||
//| skip_source_index: int,
|
||||
//| skip_dest_index: int
|
||||
//| ) -> None:
|
||||
//| """Inserts the source_bitmap region defined by rectangular boundaries
|
||||
//| (x1,y1) and (x2,y2) into the bitmap at the specified (x,y) location.
|
||||
//|
|
||||
//| :param bitmap dest_bitmap: Destination bitmap that the area will be copied into.
|
||||
//| :param bitmap source_bitmap: Source bitmap that contains the graphical region to be copied
|
||||
//| :param int x: Horizontal pixel location in bitmap where source_bitmap upper-left
|
||||
//| corner will be placed
|
||||
//| :param int y: Vertical pixel location in bitmap where source_bitmap upper-left
|
||||
//| corner will be placed
|
||||
//| :param int x1: Minimum x-value for rectangular bounding box to be copied from the source bitmap
|
||||
//| :param int y1: Minimum y-value for rectangular bounding box to be copied from the source bitmap
|
||||
//| :param int x2: Maximum x-value (exclusive) for rectangular bounding box to be copied from the source bitmap
|
||||
//| :param int y2: Maximum y-value (exclusive) for rectangular bounding box to be copied from the source bitmap
|
||||
//| :param int skip_source_index: bitmap palette index in the source that will not be copied,
|
||||
//| set to None to copy all pixels
|
||||
//| :param int skip_dest_index: bitmap palette index in the destination bitmap that will not get overwritten
|
||||
//| by the pixels from the source"""
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t bitmaptools_obj_blit(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum {ARG_destination, ARG_source, ARG_x, ARG_y, ARG_x1, ARG_y1, ARG_x2, ARG_y2, ARG_skip_source_index, ARG_skip_dest_index};
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{MP_QSTR_source_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL} },
|
||||
{MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL} },
|
||||
{MP_QSTR_x1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{MP_QSTR_y1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{MP_QSTR_x2, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to source->width
|
||||
{MP_QSTR_y2, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to source->height
|
||||
{MP_QSTR_skip_source_index, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{MP_QSTR_skip_dest_index, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
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);
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// displayio_bitmap_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
displayio_bitmap_t *destination = mp_arg_validate_type(args[ARG_destination].u_obj, &displayio_bitmap_type, MP_QSTR_dest_bitmap);
|
||||
// check_for_deinit(destination);
|
||||
|
||||
// Check x,y are within self (target) bitmap boundary
|
||||
int16_t x = mp_arg_validate_int_range(args[ARG_x].u_int, 0, MAX(0, destination->width - 1), MP_QSTR_x);
|
||||
int16_t y = mp_arg_validate_int_range(args[ARG_y].u_int, 0, MAX(0, destination->height - 1), MP_QSTR_y);
|
||||
|
||||
|
||||
displayio_bitmap_t *source = mp_arg_validate_type(args[ARG_source].u_obj, &displayio_bitmap_type, MP_QSTR_source_bitmap);
|
||||
|
||||
|
||||
// ensure that the target bitmap (self) has at least as many `bits_per_value` as the source
|
||||
if (destination->bits_per_value < source->bits_per_value) {
|
||||
mp_raise_ValueError(translate("source palette too large"));
|
||||
}
|
||||
|
||||
// Check x1,y1,x2,y2 are within source bitmap boundary
|
||||
int16_t x1 = mp_arg_validate_int_range(args[ARG_x1].u_int, 0, MAX(0, source->width - 1), MP_QSTR_x1);
|
||||
int16_t y1 = mp_arg_validate_int_range(args[ARG_y1].u_int, 0, MAX(0, source->height - 1), MP_QSTR_y1);
|
||||
int16_t x2, y2;
|
||||
// if x2 or y2 is None, then set as the maximum size of the source bitmap
|
||||
if (args[ARG_x2].u_obj == mp_const_none) {
|
||||
x2 = source->width;
|
||||
} else {
|
||||
x2 = mp_arg_validate_int_range(mp_obj_get_int(args[ARG_x2].u_obj), 0, source->width, MP_QSTR_x2);
|
||||
}
|
||||
// int16_t y2;
|
||||
if (args[ARG_y2].u_obj == mp_const_none) {
|
||||
y2 = source->height;
|
||||
} else {
|
||||
y2 = mp_arg_validate_int_range(mp_obj_get_int(args[ARG_y2].u_obj), 0, source->height, MP_QSTR_y2);
|
||||
}
|
||||
|
||||
// Ensure x1 < x2 and y1 < y2
|
||||
if (x1 > x2) {
|
||||
int16_t temp = x2;
|
||||
x2 = x1;
|
||||
x1 = temp;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
int16_t temp = y2;
|
||||
y2 = y1;
|
||||
y1 = temp;
|
||||
}
|
||||
|
||||
uint32_t skip_source_index;
|
||||
bool skip_source_index_none; // flag whether skip_value was None
|
||||
|
||||
if (args[ARG_skip_source_index].u_obj == mp_const_none) {
|
||||
skip_source_index = 0;
|
||||
skip_source_index_none = true;
|
||||
} else {
|
||||
skip_source_index = mp_obj_get_int(args[ARG_skip_source_index].u_obj);
|
||||
skip_source_index_none = false;
|
||||
}
|
||||
|
||||
uint32_t skip_dest_index;
|
||||
bool skip_dest_index_none; // flag whether skip_self_value was None
|
||||
|
||||
if (args[ARG_skip_dest_index].u_obj == mp_const_none) {
|
||||
skip_dest_index = 0;
|
||||
skip_dest_index_none = true;
|
||||
} else {
|
||||
skip_dest_index = mp_obj_get_int(args[ARG_skip_dest_index].u_obj);
|
||||
skip_dest_index_none = false;
|
||||
}
|
||||
|
||||
common_hal_bitmaptools_blit(destination, source, x, y, x1, y1, x2, y2, skip_source_index, skip_source_index_none, skip_dest_index,
|
||||
skip_dest_index_none);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_blit_obj, 1, bitmaptools_obj_blit);
|
||||
|
||||
|
||||
STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bitmaptools) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&bitmaptools_readinto_obj) },
|
||||
@ -960,6 +1086,7 @@ STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = {
|
||||
{ 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_draw_circle), MP_ROM_PTR(&bitmaptools_draw_circle_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(&bitmaptools_blit_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) },
|
||||
};
|
||||
|
@ -69,6 +69,10 @@ void common_hal_bitmaptools_draw_circle(displayio_bitmap_t *destination,
|
||||
int16_t radius,
|
||||
uint32_t value);
|
||||
|
||||
void common_hal_bitmaptools_blit(displayio_bitmap_t *destination, displayio_bitmap_t *source, int16_t x, int16_t y,
|
||||
int16_t x1, int16_t y1, int16_t x2, int16_t y2,
|
||||
uint32_t skip_source_index, bool skip_source_index_none, uint32_t skip_dest_index, bool skip_dest_index_none);
|
||||
|
||||
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);
|
||||
|
@ -186,109 +186,6 @@ STATIC mp_obj_t bitmap_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t val
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
//| def blit(
|
||||
//| self,
|
||||
//| x: int,
|
||||
//| y: int,
|
||||
//| source_bitmap: Bitmap,
|
||||
//| *,
|
||||
//| x1: int,
|
||||
//| y1: int,
|
||||
//| x2: int,
|
||||
//| y2: int,
|
||||
//| skip_index: int
|
||||
//| ) -> None:
|
||||
//| """Inserts the source_bitmap region defined by rectangular boundaries
|
||||
//| (x1,y1) and (x2,y2) into the bitmap at the specified (x,y) location.
|
||||
//|
|
||||
//| :param int x: Horizontal pixel location in bitmap where source_bitmap upper-left
|
||||
//| corner will be placed
|
||||
//| :param int y: Vertical pixel location in bitmap where source_bitmap upper-left
|
||||
//| corner will be placed
|
||||
//| :param bitmap source_bitmap: Source bitmap that contains the graphical region to be copied
|
||||
//| :param int x1: Minimum x-value for rectangular bounding box to be copied from the source bitmap
|
||||
//| :param int y1: Minimum y-value for rectangular bounding box to be copied from the source bitmap
|
||||
//| :param int x2: Maximum x-value (exclusive) for rectangular bounding box to be copied from the source bitmap
|
||||
//| :param int y2: Maximum y-value (exclusive) for rectangular bounding box to be copied from the source bitmap
|
||||
//| :param int skip_index: bitmap palette index in the source that will not be copied,
|
||||
//| set to None to copy all pixels"""
|
||||
//| ...
|
||||
STATIC mp_obj_t displayio_bitmap_obj_blit(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum {ARG_x, ARG_y, ARG_source, ARG_x1, ARG_y1, ARG_x2, ARG_y2, ARG_skip_index};
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL} },
|
||||
{MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL} },
|
||||
{MP_QSTR_source_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{MP_QSTR_x1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{MP_QSTR_y1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{MP_QSTR_x2, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to source->width
|
||||
{MP_QSTR_y2, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to source->height
|
||||
{MP_QSTR_skip_index, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} },
|
||||
};
|
||||
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_bitmap_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
check_for_deinit(self);
|
||||
|
||||
// Check x,y are within self (target) bitmap boundary
|
||||
int16_t x = mp_arg_validate_int_range(args[ARG_x].u_int, 0, MAX(0, self->width - 1), MP_QSTR_x);
|
||||
int16_t y = mp_arg_validate_int_range(args[ARG_y].u_int, 0, MAX(0, self->height - 1), MP_QSTR_y);
|
||||
|
||||
displayio_bitmap_t *source = mp_arg_validate_type(args[ARG_source].u_obj, &displayio_bitmap_type, MP_QSTR_source_bitmap);
|
||||
|
||||
|
||||
// ensure that the target bitmap (self) has at least as many `bits_per_value` as the source
|
||||
if (self->bits_per_value < source->bits_per_value) {
|
||||
mp_raise_ValueError(translate("source palette too large"));
|
||||
}
|
||||
|
||||
// Check x1,y1,x2,y2 are within source bitmap boundary
|
||||
int16_t x1 = mp_arg_validate_int_range(args[ARG_x1].u_int, 0, MAX(0, source->width - 1), MP_QSTR_x1);
|
||||
int16_t y1 = mp_arg_validate_int_range(args[ARG_y1].u_int, 0, MAX(0, source->height - 1), MP_QSTR_y1);
|
||||
int16_t x2, y2;
|
||||
// if x2 or y2 is None, then set as the maximum size of the source bitmap
|
||||
if (args[ARG_x2].u_obj == mp_const_none) {
|
||||
x2 = source->width;
|
||||
} else {
|
||||
x2 = mp_arg_validate_int_range(mp_obj_get_int(args[ARG_x2].u_obj), 0, source->width, MP_QSTR_x2);
|
||||
}
|
||||
// int16_t y2;
|
||||
if (args[ARG_y2].u_obj == mp_const_none) {
|
||||
y2 = source->height;
|
||||
} else {
|
||||
y2 = mp_arg_validate_int_range(mp_obj_get_int(args[ARG_y2].u_obj), 0, source->height, MP_QSTR_y2);
|
||||
}
|
||||
|
||||
// Ensure x1 < x2 and y1 < y2
|
||||
if (x1 > x2) {
|
||||
int16_t temp = x2;
|
||||
x2 = x1;
|
||||
x1 = temp;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
int16_t temp = y2;
|
||||
y2 = y1;
|
||||
y1 = temp;
|
||||
}
|
||||
|
||||
uint32_t skip_index;
|
||||
bool skip_index_none; // flag whether skip_value was None
|
||||
|
||||
if (args[ARG_skip_index].u_obj == mp_const_none) {
|
||||
skip_index = 0;
|
||||
skip_index_none = true;
|
||||
} else {
|
||||
skip_index = mp_obj_get_int(args[ARG_skip_index].u_obj);
|
||||
skip_index_none = false;
|
||||
}
|
||||
|
||||
common_hal_displayio_bitmap_blit(self, x, y, source, x1, y1, x2, y2, skip_index, skip_index_none);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(displayio_bitmap_blit_obj, 1, displayio_bitmap_obj_blit);
|
||||
|
||||
//| def fill(self, value: int) -> None:
|
||||
//| """Fills the bitmap with the supplied palette index value."""
|
||||
//| ...
|
||||
@ -363,7 +260,6 @@ MP_DEFINE_CONST_FUN_OBJ_1(displayio_bitmap_deinit_obj, displayio_bitmap_obj_dein
|
||||
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) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&displayio_bitmap_deinit_obj) },
|
||||
|
@ -42,9 +42,6 @@ uint16_t common_hal_displayio_bitmap_get_height(displayio_bitmap_t *self);
|
||||
uint16_t common_hal_displayio_bitmap_get_width(displayio_bitmap_t *self);
|
||||
uint32_t common_hal_displayio_bitmap_get_bits_per_value(displayio_bitmap_t *self);
|
||||
void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *bitmap, int16_t x, int16_t y, uint32_t value);
|
||||
void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16_t y, displayio_bitmap_t *source,
|
||||
int16_t x1, int16_t y1, int16_t x2, int16_t y2,
|
||||
uint32_t skip_index, bool skip_index_none);
|
||||
uint32_t common_hal_displayio_bitmap_get_pixel(displayio_bitmap_t *bitmap, int16_t x, int16_t y);
|
||||
void common_hal_displayio_bitmap_fill(displayio_bitmap_t *bitmap, uint32_t value);
|
||||
int common_hal_displayio_bitmap_get_buffer(displayio_bitmap_t *self, mp_buffer_info_t *bufinfo, mp_uint_t flags);
|
||||
|
@ -982,3 +982,71 @@ void common_hal_bitmaptools_draw_circle(displayio_bitmap_t *destination,
|
||||
|
||||
draw_circle(destination, x, y, radius, value);
|
||||
}
|
||||
|
||||
void common_hal_bitmaptools_blit(displayio_bitmap_t *destination, displayio_bitmap_t *source, int16_t x, int16_t y,
|
||||
int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint32_t skip_source_index, bool skip_source_index_none, uint32_t skip_dest_index,
|
||||
bool skip_dest_index_none) {
|
||||
|
||||
if (destination->read_only) {
|
||||
mp_raise_RuntimeError(translate("Read-only"));
|
||||
}
|
||||
// Copy region of "source" bitmap into "destination" bitmap at location x,y in the "destination"
|
||||
// If skip_value is encountered in the source bitmap, it will not be copied.
|
||||
// If skip_value is `None`, then all pixels are copied.
|
||||
// This function assumes input checks were performed for pixel index entries.
|
||||
|
||||
// Update the dirty area
|
||||
int16_t dirty_x_max = (x + (x2 - x1));
|
||||
if (dirty_x_max > destination->width) {
|
||||
dirty_x_max = destination->width;
|
||||
}
|
||||
int16_t dirty_y_max = y + (y2 - y1);
|
||||
if (dirty_y_max > destination->height) {
|
||||
dirty_y_max = destination->height;
|
||||
}
|
||||
|
||||
displayio_area_t a = { x, y, dirty_x_max, dirty_y_max, NULL};
|
||||
displayio_bitmap_set_dirty_area(destination, &a);
|
||||
|
||||
bool x_reverse = false;
|
||||
bool y_reverse = false;
|
||||
|
||||
// Add reverse direction option to protect blitting of destination bitmap back into destination bitmap
|
||||
if (x > x1) {
|
||||
x_reverse = true;
|
||||
}
|
||||
if (y > y1) {
|
||||
y_reverse = true;
|
||||
}
|
||||
|
||||
// simplest version - use internal functions for get/set pixels
|
||||
for (int16_t i = 0; i < (x2 - x1); i++) {
|
||||
|
||||
const int xs_index = x_reverse ? ((x2) - i - 1) : x1 + i; // x-index into the source bitmap
|
||||
const int xd_index = x_reverse ? ((x + (x2 - x1)) - i - 1) : x + i; // x-index into the destination bitmap
|
||||
|
||||
if ((xd_index >= 0) && (xd_index < destination->width)) {
|
||||
for (int16_t j = 0; j < (y2 - y1); j++) {
|
||||
|
||||
const int ys_index = y_reverse ? ((y2) - j - 1) : y1 + j; // y-index into the source bitmap
|
||||
const int yd_index = y_reverse ? ((y + (y2 - y1)) - j - 1) : y + j; // y-index into the destination bitmap
|
||||
|
||||
if ((yd_index >= 0) && (yd_index < destination->height)) {
|
||||
uint32_t value = common_hal_displayio_bitmap_get_pixel(source, xs_index, ys_index);
|
||||
if (skip_dest_index_none) { // if skip_dest_index is none, then only check source skip
|
||||
if ((skip_source_index_none) || (value != skip_source_index)) { // write if skip_value_none is True
|
||||
displayio_bitmap_write_pixel(destination, xd_index, yd_index, value);
|
||||
}
|
||||
} else { // check dest_value index against skip_dest_index and skip if they match
|
||||
uint32_t dest_value = common_hal_displayio_bitmap_get_pixel(destination, xd_index, yd_index);
|
||||
if (dest_value != skip_dest_index) {
|
||||
if ((skip_source_index_none) || (value != skip_source_index)) { // write if skip_value_none is True
|
||||
displayio_bitmap_write_pixel(destination, xd_index, yd_index, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -174,63 +174,6 @@ void displayio_bitmap_write_pixel(displayio_bitmap_t *self, int16_t x, int16_t y
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16_t y, displayio_bitmap_t *source,
|
||||
int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint32_t skip_index, bool skip_index_none) {
|
||||
if (self->read_only) {
|
||||
mp_raise_RuntimeError(translate("Read-only"));
|
||||
}
|
||||
// Copy region of "source" bitmap into "self" bitmap at location x,y in the "self"
|
||||
// If skip_value is encountered in the source bitmap, it will not be copied.
|
||||
// If skip_value is `None`, then all pixels are copied.
|
||||
// This function assumes input checks were performed for pixel index entries.
|
||||
|
||||
// Update the dirty area
|
||||
int16_t dirty_x_max = (x + (x2 - x1));
|
||||
if (dirty_x_max > self->width) {
|
||||
dirty_x_max = self->width;
|
||||
}
|
||||
int16_t dirty_y_max = y + (y2 - y1);
|
||||
if (dirty_y_max > self->height) {
|
||||
dirty_y_max = self->height;
|
||||
}
|
||||
|
||||
displayio_area_t a = { x, y, dirty_x_max, dirty_y_max, NULL};
|
||||
displayio_bitmap_set_dirty_area(self, &a);
|
||||
|
||||
bool x_reverse = false;
|
||||
bool y_reverse = false;
|
||||
|
||||
// Add reverse direction option to protect blitting of self bitmap back into self bitmap
|
||||
if (x > x1) {
|
||||
x_reverse = true;
|
||||
}
|
||||
if (y > y1) {
|
||||
y_reverse = true;
|
||||
}
|
||||
|
||||
// simplest version - use internal functions for get/set pixels
|
||||
for (int16_t i = 0; i < (x2 - x1); i++) {
|
||||
|
||||
const int xs_index = x_reverse ? ((x2) - i - 1) : x1 + i; // x-index into the source bitmap
|
||||
const int xd_index = x_reverse ? ((x + (x2 - x1)) - i - 1) : x + i; // x-index into the destination bitmap
|
||||
|
||||
if ((xd_index >= 0) && (xd_index < self->width)) {
|
||||
for (int16_t j = 0; j < (y2 - y1); j++) {
|
||||
|
||||
const int ys_index = y_reverse ? ((y2) - j - 1) : y1 + j; // y-index into the source bitmap
|
||||
const int yd_index = y_reverse ? ((y + (y2 - y1)) - j - 1) : y + j; // y-index into the destination bitmap
|
||||
|
||||
if ((yd_index >= 0) && (yd_index < self->height)) {
|
||||
uint32_t value = common_hal_displayio_bitmap_get_pixel(source, xs_index, ys_index);
|
||||
if ((skip_index_none) || (value != skip_index)) { // write if skip_value_none is True
|
||||
displayio_bitmap_write_pixel(self, xd_index, yd_index, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x, int16_t y, uint32_t value) {
|
||||
if (self->read_only) {
|
||||
mp_raise_RuntimeError(translate("Read-only"));
|
||||
|
Loading…
Reference in New Issue
Block a user