Skip to content

Commit 24c8d30

Browse files
committed
Can now partially blit surfaces onto the destination.
1 parent 77518d3 commit 24c8d30

File tree

3 files changed

+90
-46
lines changed

3 files changed

+90
-46
lines changed

src_c/alphablit.c

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ SoftBlitPyGame(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst,
6464

6565
int
6666
SoftCachedBlitPyGame(SDL_Surface *src, SDL_Surface *dst, int blend_flags,
67-
Uint32 ***destinations, Py_ssize_t destinations_size);
67+
BlitSequence *destinations);
6868

6969
void
70-
pg_cached_blitcopy(SDL_Surface *src, SDL_Surface *dst, Uint32 **destinations,
71-
Py_ssize_t destinations_size);
70+
pg_cached_blitcopy(SDL_Surface *src, SDL_Surface *dst,
71+
BlitSequence *destinations);
7272

7373
extern int
7474
SDL_RLESurface(SDL_Surface *surface);
@@ -590,25 +590,31 @@ SoftBlitPyGame(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst,
590590
}
591591

592592
void
593-
pg_cached_blitcopy(SDL_Surface *src, SDL_Surface *dst, Uint32 **destinations,
594-
Py_ssize_t destinations_size)
593+
pg_cached_blitcopy(SDL_Surface *src, SDL_Surface *dst,
594+
BlitSequence *destinations)
595595
{
596-
Py_ssize_t i, y;
597-
for (i = 0; i < destinations_size; i++) {
598-
Uint32 *dstp32 = destinations[i];
599-
Uint32 *srcp32 = (Uint32 *)src->pixels;
600-
y = src->h;
601-
while (y--) {
602-
memcpy(dstp32, srcp32, src->pitch);
603-
srcp32 += src->w;
604-
dstp32 += dst->w;
596+
Py_ssize_t i;
597+
for (i = 0; i < destinations->size; i++) {
598+
CachedBlitDest *item = &destinations->sequence[i];
599+
600+
const Py_ssize_t src_pitch = item->w * sizeof(Uint32);
601+
const Py_ssize_t src_skip = src->pitch / 4;
602+
const Py_ssize_t dst_skip = dst->pitch / 4;
603+
604+
Uint32 *srcp32 = (Uint32 *)src->pixels + item->x + item->y * src_skip;
605+
Uint32 *dstp32 = item->pixels;
606+
607+
while (item->h--) {
608+
memcpy(dstp32, srcp32, src_pitch);
609+
srcp32 += src_skip;
610+
dstp32 += dst_skip;
605611
}
606612
}
607613
}
608614

609615
int
610616
SoftCachedBlitPyGame(SDL_Surface *src, SDL_Surface *dst, int blend_flags,
611-
Uint32 ***destinations, Py_ssize_t destinations_size)
617+
BlitSequence *destinations)
612618
{
613619
int okay;
614620
int src_locked;
@@ -648,7 +654,7 @@ SoftCachedBlitPyGame(SDL_Surface *src, SDL_Surface *dst, int blend_flags,
648654
}
649655

650656
/* blitcopy */
651-
pg_cached_blitcopy(src, dst, *destinations, destinations_size);
657+
pg_cached_blitcopy(src, dst, destinations);
652658
break;
653659
default:
654660
okay = 0;

src_c/surface.c

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2210,8 +2210,7 @@ _surf_fblits_item_check_and_blit(pgSurfaceObject *self, PyObject *item,
22102210
int
22112211
_surf_fblits_cached_item_check_and_blit(pgSurfaceObject *self, PyObject *item,
22122212
int blend_flags,
2213-
Uint32 ***destinations,
2214-
Py_ssize_t *allocated_size)
2213+
BlitSequence *destinations)
22152214
{
22162215
PyObject *src_surf, *pos_list;
22172216
SDL_Surface *src, *dst = pgSurface_AsSurface(self);
@@ -2258,26 +2257,34 @@ _surf_fblits_cached_item_check_and_blit(pgSurfaceObject *self, PyObject *item,
22582257

22592258
/* manage destinations memory allocation or reallocation */
22602259
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) {
22642265
return FBLITS_ERR_NO_MEMORY;
22652266
}
22662267
}
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));
22712274

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;
22752282
}
2276-
*allocated_size = new_size;
22772283

22782284
/* load destinations */
22792285
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++) {
22812288
int x, y;
22822289
PyObject *tup = list_items[i];
22832290

@@ -2290,13 +2297,36 @@ _surf_fblits_cached_item_check_and_blit(pgSurfaceObject *self, PyObject *item,
22902297
return FBLITS_ERR_INCORRECT_ARGS_NUM;
22912298
}
22922299

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;
22952314
}
22962315

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+
}
22982325
}
22992326

2327+
if (!(destinations->size = current_size))
2328+
return 0;
2329+
23002330
if (self->subsurface) {
23012331
PyObject *owner;
23022332
struct pgSubSurface_Data *subdata;
@@ -2326,10 +2356,10 @@ _surf_fblits_cached_item_check_and_blit(pgSurfaceObject *self, PyObject *item,
23262356
pgSurface_Prep(self);
23272357
subsurface = NULL;
23282358
}
2359+
23292360
pgSurface_Prep((pgSurfaceObject *)src_surf);
23302361

2331-
error = SoftCachedBlitPyGame(src, dst, blend_flags, destinations,
2332-
*allocated_size);
2362+
error = SoftCachedBlitPyGame(src, dst, blend_flags, destinations);
23332363

23342364
if (subsurface)
23352365
SDL_SetClipRect(subsurface, &orig_clip);
@@ -2351,8 +2381,7 @@ surf_fblits(pgSurfaceObject *self, PyObject *const *args, Py_ssize_t nargs)
23512381
int error = 0;
23522382
int is_generator = 0;
23532383
int cache = 0;
2354-
Uint32 **destinations = NULL;
2355-
Py_ssize_t destinations_size = 0;
2384+
BlitSequence destinations = {NULL, 0, 0};
23562385

23572386
if (nargs == 0 || nargs > 3) {
23582387
error = FBLITS_ERR_INCORRECT_ARGS_NUM;
@@ -2391,8 +2420,7 @@ surf_fblits(pgSurfaceObject *self, PyObject *const *args, Py_ssize_t nargs)
23912420
item = sequence_items[i];
23922421
if (cache) {
23932422
error = _surf_fblits_cached_item_check_and_blit(
2394-
self, item, blend_flags, &destinations,
2395-
&destinations_size);
2423+
self, item, blend_flags, &destinations);
23962424
}
23972425
else {
23982426
error =
@@ -2408,8 +2436,7 @@ surf_fblits(pgSurfaceObject *self, PyObject *const *args, Py_ssize_t nargs)
24082436
while ((item = PyIter_Next(blit_sequence))) {
24092437
if (cache) {
24102438
error = _surf_fblits_cached_item_check_and_blit(
2411-
self, item, blend_flags, &destinations,
2412-
&destinations_size);
2439+
self, item, blend_flags, &destinations);
24132440
}
24142441
else {
24152442
error =
@@ -2431,15 +2458,15 @@ surf_fblits(pgSurfaceObject *self, PyObject *const *args, Py_ssize_t nargs)
24312458
goto on_error;
24322459
}
24332460

2434-
free(destinations);
2461+
free(destinations.sequence);
24352462

24362463
Py_RETURN_NONE;
24372464

24382465
on_error:
24392466
if (is_generator) {
24402467
Py_XDECREF(item);
24412468
}
2442-
free(destinations);
2469+
free(destinations.sequence);
24432470
switch (error) {
24442471
case BLITS_ERR_SEQUENCE_REQUIRED:
24452472
return RAISE(

src_c/surface.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,17 @@
337337
} while (0)
338338
#endif
339339

340+
typedef struct {
341+
Uint32 *pixels;
342+
int w, h, x, y;
343+
} CachedBlitDest;
344+
345+
typedef struct {
346+
CachedBlitDest *sequence;
347+
Py_ssize_t alloc_size;
348+
Py_ssize_t size;
349+
} BlitSequence;
350+
340351
int
341352
surface_fill_blend(SDL_Surface *surface, SDL_Rect *rect, Uint32 color,
342353
int blendargs);
@@ -354,11 +365,11 @@ pygame_Blit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst,
354365

355366
int
356367
SoftCachedBlitPyGame(SDL_Surface *src, SDL_Surface *dst, int blend_flags,
357-
Uint32 ***destinations, Py_ssize_t destinations_size);
368+
BlitSequence *destinations);
358369

359370
void
360-
pg_cached_blitcopy(SDL_Surface *src, SDL_Surface *dst, Uint32 **destinations,
361-
Py_ssize_t destinations_size);
371+
pg_cached_blitcopy(SDL_Surface *src, SDL_Surface *dst,
372+
BlitSequence *destinations);
362373

363374
int
364375
premul_surf_color_by_alpha(SDL_Surface *src, SDL_Surface *dst);

0 commit comments

Comments
 (0)