From 96d3e662b3c77804ddcd2193085aed0ec4cb9465 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sun, 2 Jul 2023 14:35:40 -0500 Subject: [PATCH] refactor bitmap.blit into bitmaptools --- shared-bindings/bitmaptools/__init__.c | 127 +++++++++++++++++++++++++ shared-bindings/bitmaptools/__init__.h | 4 + shared-bindings/displayio/Bitmap.c | 120 ----------------------- shared-bindings/displayio/Bitmap.h | 3 - shared-module/bitmaptools/__init__.c | 67 +++++++++++++ shared-module/displayio/Bitmap.c | 67 ------------- 6 files changed, 198 insertions(+), 190 deletions(-) diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c index d0aea33ef9..6d0680626d 100644 --- a/shared-bindings/bitmaptools/__init__.c +++ b/shared-bindings/bitmaptools/__init__.c @@ -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: Bitmap, +//| source_bitmap: Bitmap, +//| x: int, +//| y: int, +//| *, +//| x1: int, +//| y1: int, +//| x2: int, +//| y2: int, +//| skip_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_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_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_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_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; + } + + 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_index, skip_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) }, }; diff --git a/shared-bindings/bitmaptools/__init__.h b/shared-bindings/bitmaptools/__init__.h index 21fb1b50ab..456d2fcdfb 100644 --- a/shared-bindings/bitmaptools/__init__.h +++ b/shared-bindings/bitmaptools/__init__.h @@ -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_index, bool skip_index_none, uint32_t skip_self_index, bool skip_self_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); diff --git a/shared-bindings/displayio/Bitmap.c b/shared-bindings/displayio/Bitmap.c index 9ff8050eab..c678a76703 100644 --- a/shared-bindings/displayio/Bitmap.c +++ b/shared-bindings/displayio/Bitmap.c @@ -186,125 +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, -//| skip_self_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 -//| :param int skip_self_index: bitmap palette index in the self bitmap that will not get overwritten -//| by the pixels from the source""" -//| ... -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, ARG_skip_self_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_QSTR_skip_self_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; - } - - uint32_t skip_self_index; - bool skip_self_index_none; // flag whether skip_self_value was None - - if (args[ARG_skip_self_index].u_obj == mp_const_none) { - skip_self_index = 0; - skip_self_index_none = true; - } else { - skip_self_index = mp_obj_get_int(args[ARG_skip_self_index].u_obj); - skip_self_index_none = false; - } - - common_hal_displayio_bitmap_blit(self, x, y, source, x1, y1, x2, y2, skip_index, skip_index_none, skip_self_index, - skip_self_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.""" //| ... @@ -379,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) }, diff --git a/shared-bindings/displayio/Bitmap.h b/shared-bindings/displayio/Bitmap.h index 8f52cb8f62..8f30b3a330 100644 --- a/shared-bindings/displayio/Bitmap.h +++ b/shared-bindings/displayio/Bitmap.h @@ -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 skip_self_index, bool skip_self_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); diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index 0ded6d6abb..2b3b73030a 100644 --- a/shared-module/bitmaptools/__init__.c +++ b/shared-module/bitmaptools/__init__.c @@ -982,3 +982,70 @@ 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_index, bool skip_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_index_none) || (value != skip_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_index_none) || (value != skip_index)) { // write if skip_value_none is True + displayio_bitmap_write_pixel(destination, xd_index, yd_index, value); + } + } + } + } + } + } + } +} diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c index f8b8170395..794e2dac19 100644 --- a/shared-module/displayio/Bitmap.c +++ b/shared-module/displayio/Bitmap.c @@ -174,73 +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, uint32_t skip_self_index, - bool skip_self_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_self_index_none) { // if skip_self_index is none, then only check source skip - if ((skip_index_none) || (value != skip_index)) { // write if skip_value_none is True - displayio_bitmap_write_pixel(self, xd_index, yd_index, value); - } - } else { // check dest_value index against skip_self_index and skip if they match - uint32_t dest_value = common_hal_displayio_bitmap_get_pixel(self, xd_index, yd_index); - if (dest_value != skip_self_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"));