@@ -1985,7 +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- int draw_setbits , int draw_unsetbits , SDL_Surface * setsurf ,
1988+ int x_area_offset , int y_area_offset , int draw_setbits ,
1989+ int draw_unsetbits , SDL_Surface * setsurf ,
19891990 SDL_Surface * unsetsurf , Uint32 * setcolor , Uint32 * unsetcolor )
19901991{
19911992 Uint8 * pixel = NULL ;
@@ -2050,10 +2051,12 @@ draw_to_surface(SDL_Surface *surf, bitmask_t *bitmask, int x_dest, int y_dest,
20502051
20512052 for (y = y_start , ym = ym_start ; y < y_end ; ++ y , ++ ym ) {
20522053 pixel = (Uint8 * )surf -> pixels + y * surf -> pitch + x_start * bpp ;
2053- setpixel = (Uint8 * )setsurf -> pixels + ym * setsurf -> pitch +
2054- xm_start * bpp ;
2055- unsetpixel = (Uint8 * )unsetsurf -> pixels + ym * unsetsurf -> pitch +
2056- xm_start * bpp ;
2054+ setpixel = (Uint8 * )setsurf -> pixels +
2055+ (y_area_offset + ym ) * setsurf -> pitch +
2056+ (x_area_offset + xm_start ) * bpp ;
2057+ unsetpixel = (Uint8 * )unsetsurf -> pixels +
2058+ (y_area_offset + ym ) * unsetsurf -> pitch +
2059+ (x_area_offset + xm_start ) * bpp ;
20572060
20582061 for (x = x_start , xm = xm_start ; x < x_end ;
20592062 ++ x , ++ xm , pixel += bpp , setpixel += bpp , unsetpixel += bpp ) {
@@ -2084,13 +2087,15 @@ draw_to_surface(SDL_Surface *surf, bitmask_t *bitmask, int x_dest, int y_dest,
20842087 draw_unsetbits && NULL != unsetsurf && unsetsurf -> h > ym ;
20852088
20862089 if (use_setsurf ) {
2087- setpixel = (Uint8 * )setsurf -> pixels + ym * setsurf -> pitch +
2088- xm_start * bpp ;
2090+ setpixel = (Uint8 * )setsurf -> pixels +
2091+ (y_area_offset + ym ) * setsurf -> pitch +
2092+ (x_area_offset + xm_start ) * bpp ;
20892093 }
20902094
20912095 if (use_unsetsurf ) {
20922096 unsetpixel = (Uint8 * )unsetsurf -> pixels +
2093- ym * unsetsurf -> pitch + xm_start * bpp ;
2097+ (y_area_offset + ym ) * unsetsurf -> pitch +
2098+ (x_area_offset + xm_start ) * bpp ;
20942099 }
20952100
20962101 for (x = x_start , xm = xm_start ; x < x_end ;
@@ -2158,31 +2163,93 @@ mask_to_surface(PyObject *self, PyObject *args, PyObject *kwargs)
21582163{
21592164 PyObject * surfobj = Py_None , * setcolorobj = NULL , * unsetcolorobj = NULL ;
21602165 PyObject * setsurfobj = Py_None , * unsetsurfobj = Py_None ;
2161- PyObject * destobj = NULL ;
2166+ PyObject * destobj = NULL , * areaobj = NULL ;
2167+ SDL_Rect * area_rect , temp_rect ;
21622168 SDL_Surface * surf = NULL , * setsurf = NULL , * unsetsurf = NULL ;
2163- bitmask_t * bitmask = pgMask_AsBitmap (self );
2169+ bitmask_t * bitmask = pgMask_AsBitmap (self ), * area_bitmask ;
21642170 Uint32 * setcolor_ptr = NULL , * unsetcolor_ptr = NULL ;
21652171 Uint32 setcolor , unsetcolor ;
21662172 int draw_setbits = 0 , draw_unsetbits = 0 ;
21672173 int created_surfobj = 0 ; /* Set to 1 if this func creates the surfobj. */
21682174 int x_dest = 0 , y_dest = 0 ; /* Default destination coordinates. */
21692175 Uint8 dflt_setcolor [] = {255 , 255 , 255 , 255 }; /* Default set color. */
21702176 Uint8 dflt_unsetcolor [] = {0 , 0 , 0 , 255 }; /* Default unset color. */
2177+ int create_area_bitmask = 0 ;
21712178
21722179 static char * keywords [] = {"surface" , "setsurface" , "unsetsurface" ,
21732180 "setcolor" , "unsetcolor" , "dest" ,
2174- NULL };
2181+ "area" , NULL };
21752182
2176- if (!PyArg_ParseTupleAndKeywords (args , kwargs , "|OOOOOO" , keywords ,
2177- & surfobj , & setsurfobj , & unsetsurfobj ,
2178- & setcolorobj , & unsetcolorobj , & destobj )) {
2183+ if (!PyArg_ParseTupleAndKeywords (
2184+ args , kwargs , "|OOOOOOO" , keywords , & surfobj , & setsurfobj ,
2185+ & unsetsurfobj , & setcolorobj , & unsetcolorobj , & destobj , & areaobj )) {
21792186 return NULL ; /* Exception already set. */
21802187 }
21812188
2189+ if (NULL != destobj ) {
2190+ int tempx = 0 , tempy = 0 ;
2191+
2192+ /* Destination coordinates can be extracted from:
2193+ * - lists/tuples with 2 items
2194+ * - Rect (or Rect like) objects (uses x, y values) */
2195+ if (pg_TwoIntsFromObj (destobj , & tempx , & tempy )) {
2196+ x_dest = tempx ;
2197+ y_dest = tempy ;
2198+ }
2199+ else {
2200+ SDL_Rect temp_rect ;
2201+ SDL_Rect * dest_rect = pgRect_FromObject (destobj , & temp_rect );
2202+
2203+ if (NULL != dest_rect ) {
2204+ x_dest = dest_rect -> x ;
2205+ y_dest = dest_rect -> y ;
2206+ }
2207+ else {
2208+ PyErr_SetString (PyExc_TypeError , "invalid dest argument" );
2209+ goto to_surface_error ;
2210+ }
2211+ }
2212+ }
2213+
2214+ if (areaobj && areaobj != Py_None ) {
2215+ if (!(area_rect = pgRect_FromObject (areaobj , & temp_rect ))) {
2216+ PyErr_SetString (PyExc_TypeError , "invalid rectstyle argument" );
2217+ goto to_surface_error ;
2218+ }
2219+
2220+ memcpy (& temp_rect , area_rect , sizeof (temp_rect ));
2221+ area_rect = & temp_rect ;
2222+
2223+ pgRect_Normalize (area_rect );
2224+
2225+ if (area_rect -> x < 0 ) {
2226+ // x_dest -= area_rect->x;
2227+ area_rect -> w += area_rect -> x ;
2228+ area_rect -> x = 0 ;
2229+ }
2230+ if (area_rect -> y < 0 ) {
2231+ // y_dest -= area_rect->y;
2232+ area_rect -> h += area_rect -> y ;
2233+ area_rect -> y = 0 ;
2234+ }
2235+
2236+ // clamp rect width and height to not stick out of the mask
2237+ area_rect -> w = MAX (MIN (area_rect -> w , bitmask -> w - area_rect -> x ), 0 );
2238+ area_rect -> h = MAX (MIN (area_rect -> h , bitmask -> h - area_rect -> y ), 0 );
2239+
2240+ create_area_bitmask = 1 ;
2241+ }
2242+ else {
2243+ temp_rect .x = temp_rect .y = 0 ;
2244+ temp_rect .w = bitmask -> w ;
2245+ temp_rect .h = bitmask -> h ;
2246+ area_rect = & temp_rect ;
2247+ }
2248+
21822249 if (Py_None == surfobj ) {
2183- surfobj =
2184- PyObject_CallFunction (( PyObject * ) & pgSurface_Type , "(ii)ii" ,
2185- bitmask -> w , bitmask -> h , PGS_SRCALPHA , 32 );
2250+ surfobj = PyObject_CallFunction (( PyObject * ) & pgSurface_Type , "(ii)ii" ,
2251+ area_rect -> w , area_rect -> h ,
2252+ PGS_SRCALPHA , 32 );
21862253
21872254 if (NULL == surfobj ) {
21882255 if (!PyErr_Occurred ()) {
@@ -2266,31 +2333,6 @@ mask_to_surface(PyObject *self, PyObject *args, PyObject *kwargs)
22662333 draw_unsetbits = 1 ;
22672334 }
22682335
2269- if (NULL != destobj ) {
2270- int tempx = 0 , tempy = 0 ;
2271-
2272- /* Destination coordinates can be extracted from:
2273- * - lists/tuples with 2 items
2274- * - Rect (or Rect like) objects (uses x, y values) */
2275- if (pg_TwoIntsFromObj (destobj , & tempx , & tempy )) {
2276- x_dest = tempx ;
2277- y_dest = tempy ;
2278- }
2279- else {
2280- SDL_Rect temp_rect ;
2281- SDL_Rect * dest_rect = pgRect_FromObject (destobj , & temp_rect );
2282-
2283- if (NULL != dest_rect ) {
2284- x_dest = dest_rect -> x ;
2285- y_dest = dest_rect -> y ;
2286- }
2287- else {
2288- PyErr_SetString (PyExc_TypeError , "invalid dest argument" );
2289- goto to_surface_error ;
2290- }
2291- }
2292- }
2293-
22942336 if (!pgSurface_Lock ((pgSurfaceObject * )surfobj )) {
22952337 PyErr_SetString (PyExc_RuntimeError , "cannot lock surface" );
22962338 goto to_surface_error ;
@@ -2311,14 +2353,32 @@ mask_to_surface(PyObject *self, PyObject *args, PyObject *kwargs)
23112353 goto to_surface_error ;
23122354 }
23132355
2356+ if (create_area_bitmask ) {
2357+ area_bitmask = bitmask_create (area_rect -> w , area_rect -> h );
2358+ if (NULL == area_bitmask ) {
2359+ PyErr_Format (PyExc_MemoryError ,
2360+ "failed to allocate memory for a mask" );
2361+ return NULL ;
2362+ }
2363+
2364+ bitmask_draw (area_bitmask , bitmask , - area_rect -> x , - area_rect -> y );
2365+ }
2366+ else {
2367+ area_bitmask = bitmask ;
2368+ }
2369+
23142370 Py_BEGIN_ALLOW_THREADS ; /* Release the GIL. */
23152371
2316- draw_to_surface (surf , bitmask , x_dest , y_dest , draw_setbits ,
2317- draw_unsetbits , setsurf , unsetsurf , setcolor_ptr ,
2318- unsetcolor_ptr );
2372+ draw_to_surface (surf , area_bitmask , x_dest , y_dest , area_rect -> x ,
2373+ area_rect -> y , draw_setbits , draw_unsetbits , setsurf ,
2374+ unsetsurf , setcolor_ptr , unsetcolor_ptr );
23192375
23202376 Py_END_ALLOW_THREADS ; /* Obtain the GIL. */
23212377
2378+ if (create_area_bitmask ) {
2379+ bitmask_free (area_bitmask );
2380+ }
2381+
23222382 if (NULL != unsetsurf &&
23232383 !pgSurface_Unlock ((pgSurfaceObject * )unsetsurfobj )) {
23242384 PyErr_SetString (PyExc_RuntimeError , "cannot unlock unsetsurface" );
0 commit comments