[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[pygame] BUG?: clip and Rect anomalies when width or height negative



1. Clip Anomaly:
when a surface .set_clip is called with a rect which have negative width or height, 

seems natural that following fills or blits don't touch at all the surface.
But
width<0 --> surface.get_clip().width == surface.get_width()
height<0 --> surface.get_clip().height == surface.get_height()
so if the left,top of the clip area is not too far you get the surface partially 

blited/filled.

The attached clip_test.py demoes this.

Use case:
resizing the clip area in a loop can get the last loop iteration with a 

degenerated clip rect.
The natural control variable for the loop is not the width. 
Expectation on set_clip behavior with negative width was that nothing would write 

to the surface, hence garbage in the screen. Because of unexpected, toke some time 

to find the problem.

there is any rationale for the current behavior ?
wouldn't be better my expected behavior ?

If the current behavior will be kept, please mention it in the docs for set_clip 

and get_clip, and maybe blit / fill


2. Rect anomaly when width or height is negative:

Look at this:

>>> clip_rect = pygame.Rect(1,1,-100,-100)
>>> clip_rect.width
-100
>>> clip_rect.left
1
>>> clip_rect.right
-99
>>>

Its reasonable that a Rect can serve a width<0 ?
Its reasonable that rect.left>rect.right ?

To me, this behavior broke the user expectations. Even if the 1.8.1 docs tells 

that "The size values can be programmed to have negative values, but these are 

considered illegal Rects for most operations. "

Much better would be: Accept width or height negative, BUT convert to 0 before 

store it internally.
With that, the prev interpreter session would look:

>>> clip_rect = pygame.Rect(1,1,-100,-100)
>>> clip_rect.width
0
>>> clip_rect.left
1
>>> clip_rect.right
1
>>>

As a side effect, opers that uses rects like blit, fill, set_clip... don't need to 

be extended to the degenerate cases.

comments ?

--
claxo


# clip_test.py begin

import pygame
from pygame.constants import *

def main():
    pygame.init()
    screen = pygame.display.set_mode((800,600))
    screen.fill((109,152,6))

    dst_surf = pygame.Surface((400,400))
    dst_surf.fill((0,0,255))
    src_surf = pygame.Surface((200,200))
    src_surf.fill((255,0,0))

    print 'Initial, undisturbed dst_surf real clip rect:',dst_surf.get_clip()
    clip_rect = pygame.Rect(0,0,200,100)
    dst_surf.set_clip(clip_rect)
    print "After set_clip with a 'good' rect:",dst_surf.get_clip()

    clip_rect = pygame.Rect(0,0,-100,-100) # not ok , negative width or height ignored 
    print 'setting dst_surf clip rect to:',clip_rect
    dst_surf.set_clip(clip_rect) 
    print 'results in dst_surf real clip rect:',dst_surf.get_clip()
    dst_surf.blit(src_surf, (0,0))
    screen.blit(dst_surf,(0,0))

    pygame.display.flip()
    
    bRun = True
    while bRun:
        pygame.event.pump()
        for ev in pygame.event.get():
            if (ev.type == pygame.KEYDOWN
                and ev.key == pygame.K_ESCAPE):
                bRun = False
    pygame.quit()

if __name__ == '__main__':
    main()

# clip_test.py ends