@@ -2210,8 +2210,7 @@ _surf_fblits_item_check_and_blit(pgSurfaceObject *self, PyObject *item,
2210
2210
int
2211
2211
_surf_fblits_cached_item_check_and_blit (pgSurfaceObject * self , PyObject * item ,
2212
2212
int blend_flags ,
2213
- Uint32 * * * destinations ,
2214
- Py_ssize_t * allocated_size )
2213
+ BlitSequence * destinations )
2215
2214
{
2216
2215
PyObject * src_surf , * pos_list ;
2217
2216
SDL_Surface * src , * dst = pgSurface_AsSurface (self );
@@ -2258,26 +2257,34 @@ _surf_fblits_cached_item_check_and_blit(pgSurfaceObject *self, PyObject *item,
2258
2257
2259
2258
/* manage destinations memory allocation or reallocation */
2260
2259
Py_ssize_t new_size = PyList_GET_SIZE (pos_list );
2261
- if (!* destinations ) {
2262
- * destinations = (Uint32 * * )malloc (new_size * sizeof (Uint32 * ));
2263
- if (!* destinations ) {
2260
+ if (destinations -> sequence == NULL ) {
2261
+ destinations -> sequence =
2262
+ (CachedBlitDest * )malloc (new_size * sizeof (CachedBlitDest ));
2263
+ destinations -> size = destinations -> alloc_size = new_size ;
2264
+ if (!destinations -> sequence ) {
2264
2265
return FBLITS_ERR_NO_MEMORY ;
2265
2266
}
2266
2267
}
2267
- else {
2268
- if (new_size > * allocated_size ) {
2269
- * destinations =
2270
- (Uint32 * * )realloc (* destinations , new_size * sizeof (Uint32 * ));
2268
+ else if (new_size > 0 && new_size <= destinations -> alloc_size ) {
2269
+ destinations -> size = new_size ;
2270
+ }
2271
+ else if (new_size > destinations -> alloc_size ) {
2272
+ destinations -> sequence = (CachedBlitDest * )realloc (
2273
+ destinations -> sequence , new_size * sizeof (CachedBlitDest ));
2271
2274
2272
- if (!* destinations )
2273
- return FBLITS_ERR_NO_MEMORY ;
2274
- }
2275
+ if (!destinations -> sequence )
2276
+ return FBLITS_ERR_NO_MEMORY ;
2277
+
2278
+ destinations -> size = destinations -> alloc_size = new_size ;
2279
+ }
2280
+ else {
2281
+ return FBLITS_ERR_INCORRECT_ARGS_NUM ;
2275
2282
}
2276
- * allocated_size = new_size ;
2277
2283
2278
2284
/* load destinations */
2279
2285
PyObject * * list_items = PySequence_Fast_ITEMS (pos_list );
2280
- for (i = 0 ; i < * allocated_size ; i ++ ) {
2286
+ Py_ssize_t current_size = 0 ;
2287
+ for (i = 0 ; i < destinations -> size ; i ++ ) {
2281
2288
int x , y ;
2282
2289
PyObject * tup = list_items [i ];
2283
2290
@@ -2290,13 +2297,36 @@ _surf_fblits_cached_item_check_and_blit(pgSurfaceObject *self, PyObject *item,
2290
2297
return FBLITS_ERR_INCORRECT_ARGS_NUM ;
2291
2298
}
2292
2299
2293
- if (x < 0 || x > dst -> w - src -> w || y < 0 || y > dst -> h - src -> h ) {
2294
- return BLITS_ERR_INVALID_DESTINATION ;
2300
+ if (x < - src -> w || x > dst -> w || y < - src -> h || y > dst -> h )
2301
+ continue ; /* Skip out of bounds destinations */
2302
+
2303
+ CachedBlitDest * blit_struct = & destinations -> sequence [current_size ++ ];
2304
+ blit_struct -> pixels = (Uint32 * )dst -> pixels ;
2305
+
2306
+ if (x < 0 ) {
2307
+ blit_struct -> w = src -> w + x ;
2308
+ blit_struct -> x = - x ;
2309
+ }
2310
+ else {
2311
+ blit_struct -> pixels += x ;
2312
+ blit_struct -> w = x > dst -> w - src -> w ? dst -> w - x : src -> w ;
2313
+ blit_struct -> x = 0 ;
2295
2314
}
2296
2315
2297
- (* destinations )[i ] = (Uint32 * )dst -> pixels + y * dst -> pitch / 4 + x ;
2316
+ if (y < 0 ) {
2317
+ blit_struct -> h = src -> h + y ;
2318
+ blit_struct -> y = - y ;
2319
+ }
2320
+ else {
2321
+ blit_struct -> pixels += y * dst -> pitch / 4 ;
2322
+ blit_struct -> h = y > dst -> h - src -> h ? dst -> h - y : src -> h ;
2323
+ blit_struct -> y = 0 ;
2324
+ }
2298
2325
}
2299
2326
2327
+ if (!(destinations -> size = current_size ))
2328
+ return 0 ;
2329
+
2300
2330
if (self -> subsurface ) {
2301
2331
PyObject * owner ;
2302
2332
struct pgSubSurface_Data * subdata ;
@@ -2326,10 +2356,10 @@ _surf_fblits_cached_item_check_and_blit(pgSurfaceObject *self, PyObject *item,
2326
2356
pgSurface_Prep (self );
2327
2357
subsurface = NULL ;
2328
2358
}
2359
+
2329
2360
pgSurface_Prep ((pgSurfaceObject * )src_surf );
2330
2361
2331
- error = SoftCachedBlitPyGame (src , dst , blend_flags , destinations ,
2332
- * allocated_size );
2362
+ error = SoftCachedBlitPyGame (src , dst , blend_flags , destinations );
2333
2363
2334
2364
if (subsurface )
2335
2365
SDL_SetClipRect (subsurface , & orig_clip );
@@ -2351,8 +2381,7 @@ surf_fblits(pgSurfaceObject *self, PyObject *const *args, Py_ssize_t nargs)
2351
2381
int error = 0 ;
2352
2382
int is_generator = 0 ;
2353
2383
int cache = 0 ;
2354
- Uint32 * * destinations = NULL ;
2355
- Py_ssize_t destinations_size = 0 ;
2384
+ BlitSequence destinations = {NULL , 0 , 0 };
2356
2385
2357
2386
if (nargs == 0 || nargs > 3 ) {
2358
2387
error = FBLITS_ERR_INCORRECT_ARGS_NUM ;
@@ -2391,8 +2420,7 @@ surf_fblits(pgSurfaceObject *self, PyObject *const *args, Py_ssize_t nargs)
2391
2420
item = sequence_items [i ];
2392
2421
if (cache ) {
2393
2422
error = _surf_fblits_cached_item_check_and_blit (
2394
- self , item , blend_flags , & destinations ,
2395
- & destinations_size );
2423
+ self , item , blend_flags , & destinations );
2396
2424
}
2397
2425
else {
2398
2426
error =
@@ -2408,8 +2436,7 @@ surf_fblits(pgSurfaceObject *self, PyObject *const *args, Py_ssize_t nargs)
2408
2436
while ((item = PyIter_Next (blit_sequence ))) {
2409
2437
if (cache ) {
2410
2438
error = _surf_fblits_cached_item_check_and_blit (
2411
- self , item , blend_flags , & destinations ,
2412
- & destinations_size );
2439
+ self , item , blend_flags , & destinations );
2413
2440
}
2414
2441
else {
2415
2442
error =
@@ -2431,15 +2458,15 @@ surf_fblits(pgSurfaceObject *self, PyObject *const *args, Py_ssize_t nargs)
2431
2458
goto on_error ;
2432
2459
}
2433
2460
2434
- free (destinations );
2461
+ free (destinations . sequence );
2435
2462
2436
2463
Py_RETURN_NONE ;
2437
2464
2438
2465
on_error :
2439
2466
if (is_generator ) {
2440
2467
Py_XDECREF (item );
2441
2468
}
2442
- free (destinations );
2469
+ free (destinations . sequence );
2443
2470
switch (error ) {
2444
2471
case BLITS_ERR_SEQUENCE_REQUIRED :
2445
2472
return RAISE (
0 commit comments