Michael Rochester avatar Michael Rochester committed e2de9d5 Merge

merged

Comments (0)

Files changed (5)

 /* some constants used which are not defined on non-v4l machines. */
 #ifndef V4L2_PIX_FMT_RGB24
     #define V4L2_PIX_FMT_RGB24 'RGB3'
+#endif
+#ifndef V4L2_PIX_FMT_RGB444
     #define V4L2_PIX_FMT_RGB444 'R444'
+#endif
+#ifndef V4L2_PIX_FMT_YUYV
     #define V4L2_PIX_FMT_YUYV 'YUYV'
 #endif
 
-
-
 #define CLEAR(x) memset (&(x), 0, sizeof (x))
 #define SAT(c) if (c & (~255)) { if (c < 0) c = 0; else c = 255; }
 #define SAT2(c) ((c) & (~255) ? ((c) < 0 ? 0 : 255) : (c))
         sdlrect.y = rect->y;
         sdlrect.w = rect->w;
         sdlrect.h = rect->h;
-        
-
-
 
         // clip the rect to be within the surface.
+        if(sdlrect.x + sdlrect.w <= 0 || sdlrect.y + sdlrect.h <= 0) {
+            sdlrect.w = 0;
+            sdlrect.h = 0;
+        }
+
         if (sdlrect.x < 0) {
             sdlrect.x = 0;
         }
             sdlrect.h = sdlrect.h + (surf->h - (sdlrect.y + sdlrect.h));
         }
 
+        /* printf("%d, %d, %d, %d\n", sdlrect.x, sdlrect.y, sdlrect.w, sdlrect.h); */
 
 
         if (blendargs != 0) {
 int
 surface_fill_blend (SDL_Surface *surface, SDL_Rect *rect, Uint32 color,
                     int blendargs);
+                    
+void
+surface_respect_clip_rect (SDL_Surface *surface, SDL_Rect *rect);
 
 int 
 pygame_AlphaBlit (SDL_Surface * src, SDL_Rect * srcrect,

src/surface_fill.c

 #define NO_PYGAME_C_API
 #include "surface.h"
 
+/*
+ * Changes SDL_Rect to respect any clipping rect defined on the surface.
+ * Necessary when modifying surface->pixels directly instead of through an
+ * SDL interface.
+ */
+void surface_respect_clip_rect (SDL_Surface *surface, SDL_Rect *rect)
+{
+	SDL_Rect tmp;
+	SDL_Rect *A, *B;
+    int x, y, w, h;
+
+    A = rect;
+	B = &tmp;
+    SDL_GetClipRect(surface, B);
+	
+	/* Code here is nearly identical to rect_clip in rect.c */
+
+    /* Left */
+    if ((A->x >= B->x) && (A->x < (B->x + B->w)))
+        x = A->x;
+    else if ((B->x >= A->x) && (B->x < (A->x + A->w)))
+        x = B->x;
+    else
+        return;
+
+    /* Right */
+    if (((A->x + A->w) > B->x) && ((A->x + A->w) <= (B->x + B->w)))
+        w = (A->x + A->w) - x;
+    else if (((B->x + B->w) > A->x) && ((B->x + B->w) <= (A->x + A->w)))
+        w = (B->x + B->w) - x;
+    else
+        return;
+
+    /* Top */
+    if ((A->y >= B->y) && (A->y < (B->y + B->h)))
+        y = A->y;
+    else if ((B->y >= A->y) && (B->y < (A->y + A->h)))
+        y = B->y;
+    else
+        return;
+
+    /* Bottom */
+    if (((A->y + A->h) > B->y) && ((A->y + A->h) <= (B->y + B->h)))
+        h = (A->y + A->h) - y;
+    else if (((B->y + B->h) > A->y) && ((B->y + B->h) <= (A->y + A->h)))
+        h = (B->y + B->h) - y;
+    else
+        return;
+
+    rect->x = x;
+    rect->y = y;
+    rect->w = w;
+    rect->h = h;
+}
 
 static int
 surface_fill_blend_add (SDL_Surface *surface, SDL_Rect *rect, Uint32 color)
 {
     int result = -1;
     int locked = 0;
+    
+    surface_respect_clip_rect(surface, rect);
 
     /* Lock the surface, if needed */
     if (SDL_MUSTLOCK (surface))

test/surface_test.py

         for pt in test_utils.rect_outer_bounds(fill_rect):
             self.assert_(s1.get_at(pt) != color )
 
+
+
+    def test_fill_negative_coordinates(self):
+
+        # negative coordinates should be clipped by fill, and not draw outside the surface.
+        color = (25, 25, 25, 25)
+        color2 = (20, 20, 20, 25)
+        fill_rect = pygame.Rect(-10, -10, 16, 16)
+        
+        s1 = pygame.Surface((32,32), pygame.SRCALPHA, 32)
+        r1 = s1.fill(color, fill_rect)   
+        c = s1.get_at((0,0))
+        self.assertEqual(c, color)
+
+        # make subsurface in the middle to test it doesn't over write.
+        s2 = s1.subsurface((5, 5, 5, 5))
+        r2 = s2.fill(color2, (-3, -3, 5, 5))
+        c2 = s1.get_at((4,4))
+        self.assertEqual(c, color)
+
+        # rect returns the area we actually fill.
+        r3 = s2.fill(color2, (-30, -30, 5, 5))
+        # since we are using negative coords, it should be an zero sized rect.
+        self.assertEqual(tuple(r3), (0, 0, 0, 0))
+
+
+
+
+
     def test_fill_keyword_args(self):
         color = (1, 2, 3, 255)
         area = (1, 1, 2, 2)
             d.blit(s, (0, 0))
         sub = surf.subsurface((1, 1, 2, 2))
         self.failUnlessRaises(pygame.error, do_blit, surf, sub)
-        
+
+
+class SurfaceFillTest(unittest.TestCase):
+    def test_fill(self):
+        pygame.init()
+        try:
+            screen = pygame.display.set_mode((640, 480))
+
+            # Green and blue test pattern
+            screen.fill((0, 255, 0), (0, 0, 320, 240))
+            screen.fill((0, 255, 0), (320, 240, 320, 240))
+            screen.fill((0, 0, 255), (320, 0, 320, 240))
+            screen.fill((0, 0, 255), (0, 240, 320, 240))
+
+            # Now apply a clip rect, such that only the left side of the
+            # screen should be effected by blit opperations.
+            screen.set_clip((0, 0, 320, 480))
+
+            # Test fills with each special flag, and additionaly without any.
+            screen.fill((255, 0, 0, 127), (160, 0, 320, 30), 0)
+            screen.fill((255, 0, 0, 127), (160, 30, 320, 30), pygame.BLEND_ADD)
+            screen.fill((0, 127, 127, 127), (160, 60, 320, 30), pygame.BLEND_SUB)
+            screen.fill((0, 63, 63, 127), (160, 90, 320, 30), pygame.BLEND_MULT)
+            screen.fill((0, 127, 127, 127), (160, 120, 320, 30), pygame.BLEND_MIN)
+            screen.fill((127, 0, 0, 127), (160, 150, 320, 30), pygame.BLEND_MAX)
+            screen.fill((255, 0, 0, 127), (160, 180, 320, 30), pygame.BLEND_RGBA_ADD)
+            screen.fill((0, 127, 127, 127), (160, 210, 320, 30), pygame.BLEND_RGBA_SUB)
+            screen.fill((0, 63, 63, 127), (160, 240, 320, 30), pygame.BLEND_RGBA_MULT)
+            screen.fill((0, 127, 127, 127), (160, 270, 320, 30), pygame.BLEND_RGBA_MIN)
+            screen.fill((127, 0, 0, 127), (160, 300, 320, 30), pygame.BLEND_RGBA_MAX)
+            screen.fill((255, 0, 0, 127), (160, 330, 320, 30), pygame.BLEND_RGB_ADD)
+            screen.fill((0, 127, 127, 127), (160, 360, 320, 30), pygame.BLEND_RGB_SUB)
+            screen.fill((0, 63, 63, 127), (160, 390, 320, 30), pygame.BLEND_RGB_MULT)
+            screen.fill((0, 127, 127, 127), (160, 420, 320, 30), pygame.BLEND_RGB_MIN)
+            screen.fill((255, 0, 0, 127), (160, 450, 320, 30), pygame.BLEND_RGB_MAX)
+
+            # Update the display so we can see the results
+            pygame.display.flip()
+
+            # Compare colors on both sides of window
+            y = 5
+            while y < 480:
+                self.assertEquals(screen.get_at((10, y)),
+                        screen.get_at((330, 480 - y)))
+                y += 10
+
+        finally:
+            pygame.quit()
 
 if __name__ == '__main__':
     unittest.main()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.