@@ -1985,9 +1985,8 @@ extract_color(SDL_Surface *surf, PyObject *color_obj, Uint8 rgba_color[],
19851985 */
19861986static void
19871987draw_to_surface (SDL_Surface * surf , bitmask_t * bitmask , int x_dest , int y_dest ,
1988- SDL_Rect * area_rect , int draw_setbits , int draw_unsetbits ,
1989- SDL_Surface * setsurf , SDL_Surface * unsetsurf , Uint32 * setcolor ,
1990- Uint32 * unsetcolor )
1988+ int draw_setbits , int draw_unsetbits , SDL_Surface * setsurf ,
1989+ SDL_Surface * unsetsurf , Uint32 * setcolor , Uint32 * unsetcolor )
19911990{
19921991 Uint8 * pixel = NULL ;
19931992 Uint8 bpp ;
@@ -2003,15 +2002,6 @@ draw_to_surface(SDL_Surface *surf, bitmask_t *bitmask, int x_dest, int y_dest,
20032002 return ;
20042003 }
20052004
2006- if (area_rect -> x < 0 ) {
2007- x_dest -= area_rect -> x ;
2008- area_rect -> w += area_rect -> x ;
2009- }
2010- if (area_rect -> y < 0 ) {
2011- y_dest -= area_rect -> y ;
2012- area_rect -> h += area_rect -> y ;
2013- }
2014-
20152005 /* There is also nothing to do when the destination position is such that
20162006 * nothing will be drawn on the surface. */
20172007 if ((x_dest >= surf -> w ) || (y_dest >= surf -> h ) || (- x_dest > bitmask -> w ) ||
@@ -2021,23 +2011,13 @@ draw_to_surface(SDL_Surface *surf, bitmask_t *bitmask, int x_dest, int y_dest,
20212011
20222012 bpp = PG_SURF_BytesPerPixel (surf );
20232013
2024- // clamp rect width and height to not stick out of the mask
2025- area_rect -> w = MIN (area_rect -> w , bitmask -> w - area_rect -> x );
2026- area_rect -> h = MIN (area_rect -> h , bitmask -> h - area_rect -> y );
2027-
20282014 xm_start = (x_dest < 0 ) ? - x_dest : 0 ;
2029- if (area_rect -> x > 0 ) {
2030- xm_start += area_rect -> x ;
2031- }
20322015 x_start = (x_dest > 0 ) ? x_dest : 0 ;
2033- x_end = MIN (MIN ( surf -> w , bitmask -> w + x_dest ), x_dest + area_rect -> w );
2016+ x_end = MIN (surf -> w , bitmask -> w + x_dest );
20342017
20352018 ym_start = (y_dest < 0 ) ? - y_dest : 0 ;
2036- if (area_rect -> y > 0 ) {
2037- ym_start += area_rect -> y ;
2038- }
20392019 y_start = (y_dest > 0 ) ? y_dest : 0 ;
2040- y_end = MIN (MIN ( surf -> h , bitmask -> h + y_dest ), y_dest + area_rect -> h );
2020+ y_end = MIN (surf -> h , bitmask -> h + y_dest );
20412021
20422022 if (NULL == setsurf && NULL == unsetsurf ) {
20432023 /* Draw just using color values. No surfaces. */
@@ -2181,7 +2161,7 @@ mask_to_surface(PyObject *self, PyObject *args, PyObject *kwargs)
21812161 PyObject * destobj = NULL , * areaobj = NULL ;
21822162 SDL_Rect * area_rect , temp_rect ;
21832163 SDL_Surface * surf = NULL , * setsurf = NULL , * unsetsurf = NULL ;
2184- bitmask_t * bitmask = pgMask_AsBitmap (self );
2164+ bitmask_t * bitmask = pgMask_AsBitmap (self ), * area_bitmask ;
21852165 Uint32 * setcolor_ptr = NULL , * unsetcolor_ptr = NULL ;
21862166 Uint32 setcolor , unsetcolor ;
21872167 int draw_setbits = 0 , draw_unsetbits = 0 ;
@@ -2200,10 +2180,64 @@ mask_to_surface(PyObject *self, PyObject *args, PyObject *kwargs)
22002180 return NULL ; /* Exception already set. */
22012181 }
22022182
2183+ if (NULL != destobj ) {
2184+ int tempx = 0 , tempy = 0 ;
2185+
2186+ /* Destination coordinates can be extracted from:
2187+ * - lists/tuples with 2 items
2188+ * - Rect (or Rect like) objects (uses x, y values) */
2189+ if (pg_TwoIntsFromObj (destobj , & tempx , & tempy )) {
2190+ x_dest = tempx ;
2191+ y_dest = tempy ;
2192+ }
2193+ else {
2194+ SDL_Rect temp_rect ;
2195+ SDL_Rect * dest_rect = pgRect_FromObject (destobj , & temp_rect );
2196+
2197+ if (NULL != dest_rect ) {
2198+ x_dest = dest_rect -> x ;
2199+ y_dest = dest_rect -> y ;
2200+ }
2201+ else {
2202+ PyErr_SetString (PyExc_TypeError , "invalid dest argument" );
2203+ goto to_surface_error ;
2204+ }
2205+ }
2206+ }
2207+
2208+ if (areaobj && areaobj != Py_None ) {
2209+ if (!(area_rect = pgRect_FromObject (areaobj , & temp_rect ))) {
2210+ PyErr_SetString (PyExc_TypeError , "invalid rectstyle argument" );
2211+ goto to_surface_error ;
2212+ }
2213+ }
2214+ else {
2215+ temp_rect .x = temp_rect .y = 0 ;
2216+ temp_rect .w = bitmask -> w ;
2217+ temp_rect .h = bitmask -> h ;
2218+ area_rect = & temp_rect ;
2219+ }
2220+
2221+ if (area_rect -> x < 0 ) {
2222+ // x_dest -= area_rect->x;
2223+ area_rect -> w += area_rect -> x ;
2224+ area_rect -> x = 0 ;
2225+ }
2226+ if (area_rect -> y < 0 ) {
2227+ // y_dest -= area_rect->y;
2228+ area_rect -> h += area_rect -> y ;
2229+ area_rect -> y = 0 ;
2230+ }
2231+
2232+ // clamp rect width and height to not stick out of the mask
2233+ area_rect -> w = MAX (MIN (area_rect -> w , bitmask -> w - area_rect -> x ), 0 );
2234+ area_rect -> h = MAX (MIN (area_rect -> h , bitmask -> h - area_rect -> y ), 0 );
2235+ // pgRect_Normalize(area_rect);
2236+
22032237 if (Py_None == surfobj ) {
2204- surfobj =
2205- PyObject_CallFunction (( PyObject * ) & pgSurface_Type , "(ii)ii" ,
2206- bitmask -> w , bitmask -> h , PGS_SRCALPHA , 32 );
2238+ surfobj = PyObject_CallFunction (( PyObject * ) & pgSurface_Type , "(ii)ii" ,
2239+ area_rect -> w , area_rect -> h ,
2240+ PGS_SRCALPHA , 32 );
22072241
22082242 if (NULL == surfobj ) {
22092243 if (!PyErr_Occurred ()) {
@@ -2287,44 +2321,6 @@ mask_to_surface(PyObject *self, PyObject *args, PyObject *kwargs)
22872321 draw_unsetbits = 1 ;
22882322 }
22892323
2290- if (NULL != destobj ) {
2291- int tempx = 0 , tempy = 0 ;
2292-
2293- /* Destination coordinates can be extracted from:
2294- * - lists/tuples with 2 items
2295- * - Rect (or Rect like) objects (uses x, y values) */
2296- if (pg_TwoIntsFromObj (destobj , & tempx , & tempy )) {
2297- x_dest = tempx ;
2298- y_dest = tempy ;
2299- }
2300- else {
2301- SDL_Rect temp_rect ;
2302- SDL_Rect * dest_rect = pgRect_FromObject (destobj , & temp_rect );
2303-
2304- if (NULL != dest_rect ) {
2305- x_dest = dest_rect -> x ;
2306- y_dest = dest_rect -> y ;
2307- }
2308- else {
2309- PyErr_SetString (PyExc_TypeError , "invalid dest argument" );
2310- goto to_surface_error ;
2311- }
2312- }
2313- }
2314-
2315- if (areaobj && areaobj != Py_None ) {
2316- if (!(area_rect = pgRect_FromObject (areaobj , & temp_rect ))) {
2317- PyErr_SetString (PyExc_TypeError , "invalid rectstyle argument" );
2318- goto to_surface_error ;
2319- }
2320- }
2321- else {
2322- temp_rect .x = temp_rect .y = 0 ;
2323- temp_rect .w = bitmask -> w ;
2324- temp_rect .h = bitmask -> h ;
2325- area_rect = & temp_rect ;
2326- }
2327-
23282324 if (!pgSurface_Lock ((pgSurfaceObject * )surfobj )) {
23292325 PyErr_SetString (PyExc_RuntimeError , "cannot lock surface" );
23302326 goto to_surface_error ;
@@ -2345,14 +2341,42 @@ mask_to_surface(PyObject *self, PyObject *args, PyObject *kwargs)
23452341 goto to_surface_error ;
23462342 }
23472343
2344+ if (areaobj ) {
2345+ assert (area_rect -> w >= 0 && area_rect -> w >= 0 );
2346+ area_bitmask = bitmask_create (area_rect -> w , area_rect -> h );
2347+ if (NULL == area_bitmask ) {
2348+ PyErr_Format (PyExc_MemoryError , "failed to allocate memory for a mask" );
2349+ return NULL ;
2350+ }
2351+
2352+ bitmask_t * overlap_bitmask = bitmask_copy (area_bitmask );
2353+ if (NULL == overlap_bitmask ) {
2354+ PyErr_SetString (PyExc_MemoryError , "failed to allocate memory for a mask" );
2355+ return NULL ;
2356+ }
2357+
2358+ bitmask_fill (overlap_bitmask );
2359+
2360+ bitmask_overlap_mask (bitmask , overlap_bitmask , area_bitmask ,
2361+ area_rect -> x , area_rect -> y );
2362+ bitmask_free (overlap_bitmask );
2363+ }
2364+ else {
2365+ area_bitmask = bitmask ;
2366+ }
2367+
23482368 Py_BEGIN_ALLOW_THREADS ; /* Release the GIL. */
23492369
2350- draw_to_surface (surf , bitmask , x_dest , y_dest , area_rect , draw_setbits ,
2370+ draw_to_surface (surf , area_bitmask , x_dest , y_dest , draw_setbits ,
23512371 draw_unsetbits , setsurf , unsetsurf , setcolor_ptr ,
23522372 unsetcolor_ptr );
23532373
23542374 Py_END_ALLOW_THREADS ; /* Obtain the GIL. */
23552375
2376+ if (areaobj ) {
2377+ bitmask_free (area_bitmask );
2378+ }
2379+
23562380 if (NULL != unsetsurf &&
23572381 !pgSurface_Unlock ((pgSurfaceObject * )unsetsurfobj )) {
23582382 PyErr_SetString (PyExc_RuntimeError , "cannot unlock unsetsurface" );
0 commit comments