@@ -311,6 +311,7 @@ MAKE_ENUM_TYPE(bitmaptools, BlendMode, bitmaptools_blendmode);
311311//| blendmode: Optional[BlendMode] = BlendMode.Normal,
312312//| skip_source1_index: Union[int, None] = None,
313313//| skip_source2_index: Union[int, None] = None,
314+ //| mask: Optional[displayio.Bitmap] = None,
314315//| ) -> None:
315316//| """Alpha blend the two source bitmaps into the destination.
316317//|
@@ -326,14 +327,19 @@ MAKE_ENUM_TYPE(bitmaptools, BlendMode, bitmaptools_blendmode);
326327//| :param bitmaptools.BlendMode blendmode: The blend mode to use. Default is Normal.
327328//| :param int skip_source1_index: Bitmap palette or luminance index in source_bitmap_1 that will not be blended, set to None to blend all pixels
328329//| :param int skip_source2_index: Bitmap palette or luminance index in source_bitmap_2 that will not be blended, set to None to blend all pixels
330+ //| :param displayio.Bitmap mask: Optional 8-bits-per-value grayscale mask bitmap controlling per-pixel opacity of ``source_bitmap_2``.
331+ //| The mask must have the same width and height as the other bitmaps and a ``bits_per_value`` of 8. A mask value of 0
332+ //| means ``source_bitmap_2`` is fully transparent at that pixel (only ``source_bitmap_1`` contributes); a value of 255 means
333+ //| ``source_bitmap_2`` is fully opaque at that pixel (subject to ``factor2``). Intermediate values scale ``factor2`` linearly.
334+ //| Pass ``None`` to disable per-pixel masking.
329335//|
330336//| For the L8 colorspace, the bitmaps must have a bits-per-value of 8.
331337//| For the RGB colorspaces, they must have a bits-per-value of 16."""
332338//|
333339//|
334340
335341static mp_obj_t bitmaptools_alphablend (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
336- enum {ARG_dest_bitmap , ARG_source_bitmap_1 , ARG_source_bitmap_2 , ARG_colorspace , ARG_factor_1 , ARG_factor_2 , ARG_blendmode , ARG_skip_source1_index , ARG_skip_source2_index };
342+ enum {ARG_dest_bitmap , ARG_source_bitmap_1 , ARG_source_bitmap_2 , ARG_colorspace , ARG_factor_1 , ARG_factor_2 , ARG_blendmode , ARG_skip_source1_index , ARG_skip_source2_index , ARG_mask };
337343
338344 static const mp_arg_t allowed_args [] = {
339345 {MP_QSTR_dest_bitmap , MP_ARG_REQUIRED | MP_ARG_OBJ , {.u_obj = NULL }},
@@ -345,6 +351,7 @@ static mp_obj_t bitmaptools_alphablend(size_t n_args, const mp_obj_t *pos_args,
345351 {MP_QSTR_blendmode , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = (void * )& bitmaptools_blendmode_Normal_obj }},
346352 {MP_QSTR_skip_source1_index , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_none } },
347353 {MP_QSTR_skip_source2_index , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_none } },
354+ {MP_QSTR_mask , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_none } },
348355 };
349356 mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
350357 mp_arg_parse_all (n_args , pos_args , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
@@ -411,8 +418,19 @@ static mp_obj_t bitmaptools_alphablend(size_t n_args, const mp_obj_t *pos_args,
411418 skip_source2_index_none = false;
412419 }
413420
421+ displayio_bitmap_t * mask = NULL ;
422+ if (args [ARG_mask ].u_obj != mp_const_none ) {
423+ mask = MP_OBJ_TO_PTR (mp_arg_validate_type (args [ARG_mask ].u_obj , & displayio_bitmap_type , MP_QSTR_mask ));
424+ if (mask -> width != destination -> width || mask -> height != destination -> height ) {
425+ mp_raise_ValueError (MP_ERROR_TEXT ("Mask bitmap size must match the other bitmaps" ));
426+ }
427+ if (mask -> bits_per_value != 8 ) {
428+ mp_raise_ValueError (MP_ERROR_TEXT ("Mask bitmap must have 8 bits per pixel" ));
429+ }
430+ }
431+
414432 common_hal_bitmaptools_alphablend (destination , source1 , source2 , colorspace , factor1 , factor2 , blendmode , skip_source1_index ,
415- skip_source1_index_none , skip_source2_index , skip_source2_index_none );
433+ skip_source1_index_none , skip_source2_index , skip_source2_index_none , mask );
416434
417435 return mp_const_none ;
418436}
0 commit comments