pygame-community / pygame-ce

🐍🎮 pygame - Community Edition is a FOSS Python library for multimedia applications (like games). Built on top of the excellent SDL library.
https://pyga.me
849 stars 140 forks source link

Unhelpful error message in pygame.transform.gaussian_blur() with zero-dimensioned surfaces #2849

Closed jeremycryan closed 4 months ago

jeremycryan commented 4 months ago

Environment:

Current behavior:

When a 0-by-0 surface is passed as an argument to pygame.transform.gaussian_blur(), it raises the following exception:

ValueError: Blur routines do not support dest_surfaces that share pixels with the source surface. Likely the surfaces are the same, one of them is a subsurface, or they are sharing the same buffer.

This is doubly misleading because:

This also happens for any surface with 0 as only one of its dimensions (10x0, 0x30).

Code snippet to test this behavior:

import pygame
pygame.init()
surf = pygame.Surface((0, 0))
surf = pygame.transform.gaussian_blur(surf, 20)

Expected behavior:

Two potential fixes:

  1. Don't raise an exception. If a 0-by-0 surface is passed in, just return a new 0-by-0 surface through a copy or similar.
  2. Raise a ValueError with a different error message that specifically mentions the dimensions of the surface argument.

I'd probably personally prefer #1, since it's less likely to cause errors in code flows that might produce surfaces of variable (and sometimes zero) size, and it's a fairly intuitive way to handle size-zero surfaces. I encountered this after trying to blur the output of Pygame.font.Font.render() for an empty string.

oddbookworm commented 4 months ago

I didn’t even think it was possible to construct a surface with a zero dimension

jeremycryan commented 4 months ago

I didn’t even think it was possible to construct a surface with a zero dimension

It certainly isn't useful most of the time --- but lots of existing surface operations handle it gracefully and as expected (usually doing nothing).

The big one is probably pygame.font.Font.render() which you might want to draw nothing when a string is empty (such as a user not having typed anything in a text box yet). It currently returns a 0x0 surface when given an empty string.