@@ -949,6 +949,132 @@ STATIC mp_obj_t bitmaptools_obj_draw_circle(size_t n_args, const mp_obj_t *pos_a
949949
950950MP_DEFINE_CONST_FUN_OBJ_KW (bitmaptools_draw_circle_obj , 0 , bitmaptools_obj_draw_circle );
951951
952+ //| def blit(
953+ //| dest_bitmap: displayio.Bitmap,
954+ //| source_bitmap: displayio.Bitmap,
955+ //| x: int,
956+ //| y: int,
957+ //| *,
958+ //| x1: int,
959+ //| y1: int,
960+ //| x2: int,
961+ //| y2: int,
962+ //| skip_source_index: int,
963+ //| skip_dest_index: int
964+ //| ) -> None:
965+ //| """Inserts the source_bitmap region defined by rectangular boundaries
966+ //| (x1,y1) and (x2,y2) into the bitmap at the specified (x,y) location.
967+ //|
968+ //| :param bitmap dest_bitmap: Destination bitmap that the area will be copied into.
969+ //| :param bitmap source_bitmap: Source bitmap that contains the graphical region to be copied
970+ //| :param int x: Horizontal pixel location in bitmap where source_bitmap upper-left
971+ //| corner will be placed
972+ //| :param int y: Vertical pixel location in bitmap where source_bitmap upper-left
973+ //| corner will be placed
974+ //| :param int x1: Minimum x-value for rectangular bounding box to be copied from the source bitmap
975+ //| :param int y1: Minimum y-value for rectangular bounding box to be copied from the source bitmap
976+ //| :param int x2: Maximum x-value (exclusive) for rectangular bounding box to be copied from the source bitmap
977+ //| :param int y2: Maximum y-value (exclusive) for rectangular bounding box to be copied from the source bitmap
978+ //| :param int skip_source_index: bitmap palette index in the source that will not be copied,
979+ //| set to None to copy all pixels
980+ //| :param int skip_dest_index: bitmap palette index in the destination bitmap that will not get overwritten
981+ //| by the pixels from the source"""
982+ //| ...
983+ //|
984+ STATIC mp_obj_t bitmaptools_obj_blit (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
985+ 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 };
986+ static const mp_arg_t allowed_args [] = {
987+ {MP_QSTR_dest_bitmap , MP_ARG_REQUIRED | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
988+ {MP_QSTR_source_bitmap , MP_ARG_REQUIRED | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
989+ {MP_QSTR_x , MP_ARG_REQUIRED | MP_ARG_INT , {.u_obj = MP_OBJ_NULL } },
990+ {MP_QSTR_y , MP_ARG_REQUIRED | MP_ARG_INT , {.u_obj = MP_OBJ_NULL } },
991+ {MP_QSTR_x1 , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 } },
992+ {MP_QSTR_y1 , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 } },
993+ {MP_QSTR_x2 , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_none } }, // None convert to source->width
994+ {MP_QSTR_y2 , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_none } }, // None convert to source->height
995+ {MP_QSTR_skip_source_index , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_none } },
996+ {MP_QSTR_skip_dest_index , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_none } },
997+ };
998+ mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
999+ // mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
1000+ mp_arg_parse_all (n_args , pos_args , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
1001+
1002+ // displayio_bitmap_t *self = MP_OBJ_TO_PTR(pos_args[0]);
1003+ displayio_bitmap_t * destination = mp_arg_validate_type (args [ARG_destination ].u_obj , & displayio_bitmap_type , MP_QSTR_dest_bitmap );
1004+ // check_for_deinit(destination);
1005+
1006+ // Check x,y are within self (target) bitmap boundary
1007+ int16_t x = mp_arg_validate_int_range (args [ARG_x ].u_int , 0 , MAX (0 , destination -> width - 1 ), MP_QSTR_x );
1008+ int16_t y = mp_arg_validate_int_range (args [ARG_y ].u_int , 0 , MAX (0 , destination -> height - 1 ), MP_QSTR_y );
1009+
1010+
1011+ displayio_bitmap_t * source = mp_arg_validate_type (args [ARG_source ].u_obj , & displayio_bitmap_type , MP_QSTR_source_bitmap );
1012+
1013+
1014+ // ensure that the target bitmap (self) has at least as many `bits_per_value` as the source
1015+ if (destination -> bits_per_value < source -> bits_per_value ) {
1016+ mp_raise_ValueError (translate ("source palette too large" ));
1017+ }
1018+
1019+ // Check x1,y1,x2,y2 are within source bitmap boundary
1020+ int16_t x1 = mp_arg_validate_int_range (args [ARG_x1 ].u_int , 0 , MAX (0 , source -> width - 1 ), MP_QSTR_x1 );
1021+ int16_t y1 = mp_arg_validate_int_range (args [ARG_y1 ].u_int , 0 , MAX (0 , source -> height - 1 ), MP_QSTR_y1 );
1022+ int16_t x2 , y2 ;
1023+ // if x2 or y2 is None, then set as the maximum size of the source bitmap
1024+ if (args [ARG_x2 ].u_obj == mp_const_none ) {
1025+ x2 = source -> width ;
1026+ } else {
1027+ x2 = mp_arg_validate_int_range (mp_obj_get_int (args [ARG_x2 ].u_obj ), 0 , source -> width , MP_QSTR_x2 );
1028+ }
1029+ // int16_t y2;
1030+ if (args [ARG_y2 ].u_obj == mp_const_none ) {
1031+ y2 = source -> height ;
1032+ } else {
1033+ y2 = mp_arg_validate_int_range (mp_obj_get_int (args [ARG_y2 ].u_obj ), 0 , source -> height , MP_QSTR_y2 );
1034+ }
1035+
1036+ // Ensure x1 < x2 and y1 < y2
1037+ if (x1 > x2 ) {
1038+ int16_t temp = x2 ;
1039+ x2 = x1 ;
1040+ x1 = temp ;
1041+ }
1042+ if (y1 > y2 ) {
1043+ int16_t temp = y2 ;
1044+ y2 = y1 ;
1045+ y1 = temp ;
1046+ }
1047+
1048+ uint32_t skip_source_index ;
1049+ bool skip_source_index_none ; // flag whether skip_value was None
1050+
1051+ if (args [ARG_skip_source_index ].u_obj == mp_const_none ) {
1052+ skip_source_index = 0 ;
1053+ skip_source_index_none = true;
1054+ } else {
1055+ skip_source_index = mp_obj_get_int (args [ARG_skip_source_index ].u_obj );
1056+ skip_source_index_none = false;
1057+ }
1058+
1059+ uint32_t skip_dest_index ;
1060+ bool skip_dest_index_none ; // flag whether skip_self_value was None
1061+
1062+ if (args [ARG_skip_dest_index ].u_obj == mp_const_none ) {
1063+ skip_dest_index = 0 ;
1064+ skip_dest_index_none = true;
1065+ } else {
1066+ skip_dest_index = mp_obj_get_int (args [ARG_skip_dest_index ].u_obj );
1067+ skip_dest_index_none = false;
1068+ }
1069+
1070+ common_hal_bitmaptools_blit (destination , source , x , y , x1 , y1 , x2 , y2 , skip_source_index , skip_source_index_none , skip_dest_index ,
1071+ skip_dest_index_none );
1072+
1073+ return mp_const_none ;
1074+ }
1075+ MP_DEFINE_CONST_FUN_OBJ_KW (bitmaptools_blit_obj , 1 , bitmaptools_obj_blit );
1076+
1077+
9521078STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table [] = {
9531079 { MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR_bitmaptools ) },
9541080 { 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[] = {
9601086 { MP_ROM_QSTR (MP_QSTR_draw_line ), MP_ROM_PTR (& bitmaptools_draw_line_obj ) },
9611087 { MP_ROM_QSTR (MP_QSTR_draw_polygon ), MP_ROM_PTR (& bitmaptools_draw_polygon_obj ) },
9621088 { MP_ROM_QSTR (MP_QSTR_draw_circle ), MP_ROM_PTR (& bitmaptools_draw_circle_obj ) },
1089+ { MP_ROM_QSTR (MP_QSTR_blit ), MP_ROM_PTR (& bitmaptools_blit_obj ) },
9631090 { MP_ROM_QSTR (MP_QSTR_dither ), MP_ROM_PTR (& bitmaptools_dither_obj ) },
9641091 { MP_ROM_QSTR (MP_QSTR_DitherAlgorithm ), MP_ROM_PTR (& bitmaptools_dither_algorithm_type ) },
9651092};
0 commit comments