@@ -172,7 +172,109 @@ STATIC mp_obj_t bitmap_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t val
172
172
return mp_const_none ;
173
173
}
174
174
175
- //| def fill(self, value: int) -> None:
175
+ //| def blit(self, x: int, y: int, source_bitmap: bitmap, *, x1: int, y1: int, x2: int, y2: int, skip_index: int) -> None:
176
+ //| """Inserts the source_bitmap region defined by rectangular boundaries
177
+ //| (x1,y1) and (x2,y2) into the bitmap at the specified (x,y) location.
178
+ //|
179
+ //| :param int x: Horizontal pixel location in bitmap where source_bitmap upper-left
180
+ //| corner will be placed
181
+ //| :param int y: Vertical pixel location in bitmap where source_bitmap upper-left
182
+ //| corner will be placed
183
+ //| :param bitmap source_bitmap: Source bitmap that contains the graphical region to be copied
184
+ //| :param int x1: Minimum x-value for rectangular bounding box to be copied from the source bitmap
185
+ //| :param int y1: Minimum y-value for rectangular bounding box to be copied from the source bitmap
186
+ //| :param int x2: Maximum x-value (exclusive) for rectangular bounding box to be copied from the source bitmap
187
+ //| :param int y2: Maximum y-value (exclusive) for rectangular bounding box to be copied from the source bitmap
188
+ //| :param int skip_index: bitmap palette index in the source that will not be copied,
189
+ //| set to None to copy all pixels"""
190
+ //| ...
191
+ //|
192
+ STATIC mp_obj_t displayio_bitmap_obj_blit (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ){
193
+ enum {ARG_x , ARG_y , ARG_source , ARG_x1 , ARG_y1 , ARG_x2 , ARG_y2 , ARG_skip_index };
194
+ static const mp_arg_t allowed_args [] = {
195
+ {MP_QSTR_x , MP_ARG_REQUIRED | MP_ARG_INT },
196
+ {MP_QSTR_y , MP_ARG_REQUIRED | MP_ARG_INT },
197
+ {MP_QSTR_source_bitmap , MP_ARG_REQUIRED | MP_ARG_OBJ },
198
+ {MP_QSTR_x1 , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 } },
199
+ {MP_QSTR_y1 , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 } },
200
+ {MP_QSTR_x2 , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_none } }, // None convert to source->width
201
+ {MP_QSTR_y2 , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_none } }, // None convert to source->height
202
+ {MP_QSTR_skip_index , MP_ARG_OBJ | MP_ARG_KW_ONLY , {.u_obj = mp_const_none } },
203
+ };
204
+ mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
205
+ mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
206
+
207
+ displayio_bitmap_t * self = MP_OBJ_TO_PTR (pos_args [0 ]);
208
+
209
+ int16_t x = args [ARG_x ].u_int ;
210
+ int16_t y = args [ARG_y ].u_int ;
211
+
212
+ displayio_bitmap_t * source = MP_OBJ_TO_PTR (args [ARG_source ].u_obj );
213
+
214
+ // ensure that the target bitmap (self) has at least as many `bits_per_value` as the source
215
+ if (self -> bits_per_value < source -> bits_per_value ) {
216
+ mp_raise_ValueError (translate ("source palette too large" ));
217
+ }
218
+
219
+ int16_t x1 = args [ARG_x1 ].u_int ;
220
+ int16_t y1 = args [ARG_y1 ].u_int ;
221
+ int16_t x2 , y2 ;
222
+ // if x2 or y2 is None, then set as the maximum size of the source bitmap
223
+ if ( args [ARG_x2 ].u_obj == mp_const_none ) {
224
+ x2 = source -> width ;
225
+ } else {
226
+ x2 = mp_obj_get_int (args [ARG_x2 ].u_obj );
227
+ }
228
+ //int16_t y2;
229
+ if ( args [ARG_y2 ].u_obj == mp_const_none ) {
230
+ y2 = source -> height ;
231
+ } else {
232
+ y2 = mp_obj_get_int (args [ARG_y2 ].u_obj );
233
+ }
234
+
235
+ // Check x,y are within self (target) bitmap boundary
236
+ if ( (x < 0 ) || (y < 0 ) || (x > self -> width ) || (y > self -> height ) ) {
237
+ mp_raise_ValueError (translate ("out of range of target" ));
238
+ }
239
+ // Check x1,y1,x2,y2 are within source bitmap boundary
240
+ if ( (x1 < 0 ) || (x1 > source -> width ) ||
241
+ (y1 < 0 ) || (y1 > source -> height ) ||
242
+ (x2 < 0 ) || (x2 > source -> width ) ||
243
+ (y2 < 0 ) || (y2 > source -> height ) ) {
244
+ mp_raise_ValueError (translate ("out of range of source" ));
245
+ }
246
+
247
+ // Ensure x1 < x2 and y1 < y2
248
+ if (x1 > x2 ) {
249
+ int16_t temp = x2 ;
250
+ x2 = x1 ;
251
+ x1 = temp ;
252
+ }
253
+ if (y1 > y2 ) {
254
+ int16_t temp = y2 ;
255
+ y2 = y1 ;
256
+ y1 = temp ;
257
+ }
258
+
259
+ uint32_t skip_index ;
260
+ bool skip_index_none ; // flag whether skip_value was None
261
+
262
+ if (args [ARG_skip_index ].u_obj == mp_const_none ) {
263
+ skip_index = 0 ;
264
+ skip_index_none = true;
265
+ } else {
266
+ skip_index = mp_obj_get_int (args [ARG_skip_index ].u_obj );
267
+ skip_index_none = false;
268
+ }
269
+
270
+ common_hal_displayio_bitmap_blit (self , x , y , source , x1 , y1 , x2 , y2 , skip_index , skip_index_none );
271
+
272
+ return mp_const_none ;
273
+ }
274
+ MP_DEFINE_CONST_FUN_OBJ_KW (displayio_bitmap_blit_obj , 4 , displayio_bitmap_obj_blit );
275
+ // `displayio_bitmap_obj_blit` requires at least 4 arguments
276
+
277
+ //| def fill(self, value: Any) -> None:
176
278
//| """Fills the bitmap with the supplied palette index value."""
177
279
//| ...
178
280
//|
@@ -192,6 +294,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(displayio_bitmap_fill_obj, displayio_bitmap_obj_fill);
192
294
STATIC const mp_rom_map_elem_t displayio_bitmap_locals_dict_table [] = {
193
295
{ MP_ROM_QSTR (MP_QSTR_height ), MP_ROM_PTR (& displayio_bitmap_height_obj ) },
194
296
{ MP_ROM_QSTR (MP_QSTR_width ), MP_ROM_PTR (& displayio_bitmap_width_obj ) },
297
+ { MP_ROM_QSTR (MP_QSTR_blit ), MP_ROM_PTR (& displayio_bitmap_blit_obj ) },
195
298
{ MP_ROM_QSTR (MP_QSTR_fill ), MP_ROM_PTR (& displayio_bitmap_fill_obj ) },
196
299
197
300
};
0 commit comments