@@ -1985,7 +1985,8 @@ extract_color(SDL_Surface *surf, PyObject *color_obj, Uint8 rgba_color[],
1985
1985
*/
1986
1986
static void
1987
1987
draw_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 ,
1989
1990
SDL_Surface * unsetsurf , Uint32 * setcolor , Uint32 * unsetcolor )
1990
1991
{
1991
1992
Uint8 * pixel = NULL ;
@@ -2050,10 +2051,12 @@ draw_to_surface(SDL_Surface *surf, bitmask_t *bitmask, int x_dest, int y_dest,
2050
2051
2051
2052
for (y = y_start , ym = ym_start ; y < y_end ; ++ y , ++ ym ) {
2052
2053
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 ;
2057
2060
2058
2061
for (x = x_start , xm = xm_start ; x < x_end ;
2059
2062
++ 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,
2084
2087
draw_unsetbits && NULL != unsetsurf && unsetsurf -> h > ym ;
2085
2088
2086
2089
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 ;
2089
2093
}
2090
2094
2091
2095
if (use_unsetsurf ) {
2092
2096
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 ;
2094
2099
}
2095
2100
2096
2101
for (x = x_start , xm = xm_start ; x < x_end ;
@@ -2158,31 +2163,93 @@ mask_to_surface(PyObject *self, PyObject *args, PyObject *kwargs)
2158
2163
{
2159
2164
PyObject * surfobj = Py_None , * setcolorobj = NULL , * unsetcolorobj = NULL ;
2160
2165
PyObject * setsurfobj = Py_None , * unsetsurfobj = Py_None ;
2161
- PyObject * destobj = NULL ;
2166
+ PyObject * destobj = NULL , * areaobj = NULL ;
2167
+ SDL_Rect * area_rect , temp_rect ;
2162
2168
SDL_Surface * surf = NULL , * setsurf = NULL , * unsetsurf = NULL ;
2163
- bitmask_t * bitmask = pgMask_AsBitmap (self );
2169
+ bitmask_t * bitmask = pgMask_AsBitmap (self ), * area_bitmask ;
2164
2170
Uint32 * setcolor_ptr = NULL , * unsetcolor_ptr = NULL ;
2165
2171
Uint32 setcolor , unsetcolor ;
2166
2172
int draw_setbits = 0 , draw_unsetbits = 0 ;
2167
2173
int created_surfobj = 0 ; /* Set to 1 if this func creates the surfobj. */
2168
2174
int x_dest = 0 , y_dest = 0 ; /* Default destination coordinates. */
2169
2175
Uint8 dflt_setcolor [] = {255 , 255 , 255 , 255 }; /* Default set color. */
2170
2176
Uint8 dflt_unsetcolor [] = {0 , 0 , 0 , 255 }; /* Default unset color. */
2177
+ int create_area_bitmask = 0 ;
2171
2178
2172
2179
static char * keywords [] = {"surface" , "setsurface" , "unsetsurface" ,
2173
2180
"setcolor" , "unsetcolor" , "dest" ,
2174
- NULL };
2181
+ "area" , NULL };
2175
2182
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 )) {
2179
2186
return NULL ; /* Exception already set. */
2180
2187
}
2181
2188
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
+
2182
2249
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 );
2186
2253
2187
2254
if (NULL == surfobj ) {
2188
2255
if (!PyErr_Occurred ()) {
@@ -2266,31 +2333,6 @@ mask_to_surface(PyObject *self, PyObject *args, PyObject *kwargs)
2266
2333
draw_unsetbits = 1 ;
2267
2334
}
2268
2335
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
-
2294
2336
if (!pgSurface_Lock ((pgSurfaceObject * )surfobj )) {
2295
2337
PyErr_SetString (PyExc_RuntimeError , "cannot lock surface" );
2296
2338
goto to_surface_error ;
@@ -2311,14 +2353,32 @@ mask_to_surface(PyObject *self, PyObject *args, PyObject *kwargs)
2311
2353
goto to_surface_error ;
2312
2354
}
2313
2355
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
+
2314
2370
Py_BEGIN_ALLOW_THREADS ; /* Release the GIL. */
2315
2371
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 );
2319
2375
2320
2376
Py_END_ALLOW_THREADS ; /* Obtain the GIL. */
2321
2377
2378
+ if (create_area_bitmask ) {
2379
+ bitmask_free (area_bitmask );
2380
+ }
2381
+
2322
2382
if (NULL != unsetsurf &&
2323
2383
!pgSurface_Unlock ((pgSurfaceObject * )unsetsurfobj )) {
2324
2384
PyErr_SetString (PyExc_RuntimeError , "cannot unlock unsetsurface" );
0 commit comments