From 345d9bfe192493cbaf7cc547a00c0ad1d1e3bf1b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 25 Sep 2024 22:15:20 -0700 Subject: [PATCH] A zero source rect is valid for blitting A zero sized source rect draws pixels sourced from a 0x0 region on the source surface. Fixes https://github.com/libsdl-org/SDL/issues/8580 --- src/video/SDL_blit.c | 2 +- src/video/SDL_surface.c | 2 +- test/testautomation_surface.c | 26 ++++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/video/SDL_blit.c b/src/video/SDL_blit.c index c853accf91..2e782bdb4c 100644 --- a/src/video/SDL_blit.c +++ b/src/video/SDL_blit.c @@ -59,7 +59,7 @@ static bool SDLCALL SDL_SoftBlit(SDL_Surface *src, const SDL_Rect *srcrect, } // Set up source and destination buffer pointers, and BLIT! - if (okay && !SDL_RectEmpty(srcrect)) { + if (okay) { SDL_BlitFunc RunBlit; SDL_BlitInfo *info = &src->internal->map.info; diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index 26df19a12e..46c1626fc5 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -1226,7 +1226,7 @@ bool SDL_BlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surfac SDL_GetRectIntersection(clip_rect, &final_dst, &final_dst); if (final_dst.w == 0 || final_dst.h == 0 || - final_src.w <= 0 || final_src.h <= 0) { + final_src.w < 0 || final_src.h < 0) { // No-op. return true; } diff --git a/test/testautomation_surface.c b/test/testautomation_surface.c index 838fe8f291..7ba11caac4 100644 --- a/test/testautomation_surface.c +++ b/test/testautomation_surface.c @@ -821,6 +821,27 @@ static int SDLCALL surface_testLoadFailure(void *arg) return TEST_COMPLETED; } +/** + * Tests blitting from a zero sized source rectangle + */ +static int SDLCALL surface_testBlitZeroSource(void *arg) +{ + SDL_Surface *src = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_RGBA8888); + SDL_Surface *dst = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_RGBA8888); + SDL_Rect srcrect = { 0, 0, 0, 0 }; + int ret; + + SDLTest_AssertPass("Call to SDL_BlitSurfaceScaled() with zero sized source rectangle"); + SDL_FillSurfaceRect(src, NULL, SDL_MapSurfaceRGB(src, 255, 255, 255)); + SDL_BlitSurfaceScaled(src, &srcrect, dst, NULL, SDL_SCALEMODE_NEAREST); + ret = SDLTest_CompareSurfaces(dst, src, 0); + SDLTest_AssertCheck(ret == 0, "Validate result from SDLTest_CompareSurfaces, expected: 0, got: %i", ret); + SDL_DestroySurface(src); + SDL_DestroySurface(dst); + + return TEST_COMPLETED; +} + /** * Tests some blitting routines. */ @@ -1465,6 +1486,10 @@ static const SDLTest_TestCaseReference surfaceTestSaveLoadBitmap = { surface_testSaveLoadBitmap, "surface_testSaveLoadBitmap", "Tests sprite saving and loading.", TEST_ENABLED }; +static const SDLTest_TestCaseReference surfaceTestBlitZeroSource = { + surface_testBlitZeroSource, "surface_testBlitZeroSource", "Tests blitting from a zero sized source rectangle", TEST_ENABLED +}; + static const SDLTest_TestCaseReference surfaceTestBlit = { surface_testBlit, "surface_testBlit", "Tests basic blitting.", TEST_ENABLED }; @@ -1552,6 +1577,7 @@ static const SDLTest_TestCaseReference surfaceTestPremultiplyAlpha = { /* Sequence of Surface test cases */ static const SDLTest_TestCaseReference *surfaceTests[] = { &surfaceTestSaveLoadBitmap, + &surfaceTestBlitZeroSource, &surfaceTestBlit, &surfaceTestBlitTiled, &surfaceTestBlit9Grid,