Commits

Anonymous committed 00c2125

Documentation for pygame.draw. Allow negative width/height in rect.

Comments (0)

Files changed (3)

 
 pygame:
 dealloc surface
+mac default icon
+#!/usr/bin/env python
+
+'''Pygame module for drawing shapes.
+
+Draw several simple shapes to a Surface. These functions will work for
+rendering to any format of Surface. Rendering to hardware Surfaces will
+be slower than regular software Surfaces.
+
+Most of the functions take a width argument to represent the size of
+stroke around the edge of the shape. If a width of 0 is passed the
+function will actually solid fill the entire shape.
+
+All the drawing functions respect the clip area for the Surface, and
+will be constrained to that area. The functions return a rectangle
+representing the bounding area of changed pixels.
+
+Most of the arguments accept a color argument that is an RGB triplet.
+These can also accept an RGBA quadruplet. The alpha value will be written
+directly into the Surface if it contains pixel alphas, but the draw
+function will not draw transparently. The color argument can also be an
+integer pixel value that is already mapped to the Surface's pixel format.
+
+These functions must temporarily lock the Surface they are operating on.
+Many sequential drawing calls can be sped up by locking and unlocking
+the Surface object around the draw calls.
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id$'
+
+def rect(surface, color, rect, width=0):
+    '''Draw a rectangle shape.
+
+    Draws a rectangular shape on the Surface. The given Rect is the area of
+    the rectangle. The width argument is the thickness to draw the outer edge.
+    If width is zero then the rectangle will be filled.
+     
+    Keep in mind the Surface.fill() method works just as well for drawing
+    filled rectangles. In fact the Surface.fill() can be hardware accelerated
+    on some platforms with both software and hardware display modes.
+
+    :Parameters:
+        `surface` : `Surface`
+            Surface to draw on.
+        `color` : int, int, int
+            RGB fill color.
+        `rect` : `Rect` or int, int, int, int
+            Rectangle boundary.
+        `width` : int
+            Edge thickness, or zero to fill region.
+
+    :rtype: `Rect`
+    :return: Affected bounding box.
+    '''    
+
+def polygon(surface, color, pointlist, width=0):
+    '''Draw a shape with any number of sides.
+
+    Draws a polygonal shape on the Surface. The pointlist argument is the
+    vertices of the polygon. The width argument is the thickness to draw the
+    outer edge. If width is zero then the polygon will be filled.
+
+    For aapolygon, use aalines with the 'closed' parameter.
+    
+    :Parameters:
+        `surface` : `Surface`
+            Surface to draw on.
+        `color` : int, int, int
+            RGB fill color.
+        `pointlist` : list of (int, int)
+            Each list element is a vertex of the polygon.
+        `width` : int
+            Edge thickness, or zero to fill region.
+
+    :rtype: `Rect`
+    :return: Affected bounding box.
+    '''    
+
+def circle(surface, color, pos, radius, width=0):
+    '''Draw a circle around a point.
+
+    Draws a circular shape on the Surface. The pos argument is the center of
+    the circle, and radius is the size. The width argument is the thickness to
+    draw the outer edge. If width is zero then the circle will be filled.
+
+    :Parameters:
+        `surface` : `Surface`
+            Surface to draw on.
+        `color` : int, int, int
+            RGB fill color.
+        `pos` : int, int
+            Center point of circle.
+        `radius` : int
+            Radius of circle, in pixels.
+        `width` : int
+            Edge thickness, or zero to fill region.
+
+    :rtype: `Rect`
+    :return: Affected bounding box.
+    '''     
+
+def ellipse(surface, color, rect, width=0):
+    '''Draw a round shape inside a rectangle.
+
+    Draws an elliptical shape on the Surface. The given rectangle is the area
+    that the circle will fill. The width argument is the thickness to draw the
+    outer edge. If width is zero then the ellipse will be filled.
+    
+    :Parameters:
+        `surface` : `Surface`
+            Surface to draw on.
+        `color` : int, int, int
+            RGB fill color.
+        `rect` : `Rect` or int, int, int, int
+            Ellipse boundary.
+        `width` : int
+            Edge thickness, or zero to fill region.
+
+    :rtype: `Rect`
+    :return: Affected bounding box.
+    '''     
+
+def arc(surface, color, rect, start_angle, stop_angle, width=1):
+    '''Draw a partial section of an ellipse.
+
+    Draws an elliptical arc on the Surface. The rect argument is the area that
+    the ellipse will fill. The two angle arguments are the initial and final
+    angle in radians, with the zero on the right. The width argument is the
+    thickness to draw the outer edge.
+
+    :Parameters:
+        `surface` : `Surface`
+            Surface to draw on.
+        `color` : int, int, int
+            RGB fill color.
+        `rect` : `Rect` or int, int, int, int
+            Ellipse boundary.
+        `start_angle` : float
+            Angle to start drawing arc at, in radians.
+        `stop_angle` : float
+            Angle to stop drawing arc at, in radians.
+        `width` : int
+            Edge thickness.
+
+    :rtype: `Rect`
+    :return: Affected bounding box.
+    '''     
+
+def line(surface, color, start_pos, end_pos, width=1):
+    '''Draw a straight line segment.
+
+    Draw a straight line segment on a Surface. There are no endcaps, the
+    ends are squared off for thick lines.
+
+    :Parameters:
+        `surface` : `Surface`
+            Surface to draw on.
+        `color` : int, int, int
+            RGB fill color.
+        `start_pos` : int, int
+            X, Y coordinates of first vertex.
+        `end_pos` : int, int
+            X, Y coordinates of second vertex.
+        `width` : int
+            Line thickness.
+
+    :rtype: `Rect`
+    :return: Affected bounding box.
+    '''
+    
+def lines(surface, color, closed, pointlist, width=1):
+    '''Draw multiple contiguous line segments.
+
+    Draw a sequence of lines on a Surface. The pointlist argument is a series
+    of points that are connected by a line. If the closed argument is true an
+    additional line segment is drawn between the first and last points.
+
+    This does not draw any endcaps or miter joints. Lines with sharp corners
+    and wide line widths can have improper looking corners.
+    
+    :Parameters:
+        `surface` : `Surface`
+            Surface to draw on.
+        `color` : int, int, int
+            RGB fill color.
+        `closed` : bool
+            True if line segments form a closed polygon, otherwise False.
+        `pointlist` : list of (int, int)
+            List of X, Y coordinates giving vertices.
+        `width` : int
+            Line thickness.
+
+    :rtype: `Rect`
+    :return: Affected bounding box.
+    '''
+
+def aaline(surface, color, startpos, endpos, blend=1):
+    '''Draw a line with antialiasing.
+
+    Draws an anti-aliased line on a surface. This will respect the clipping
+    rectangle. A bounding box of the affected area is returned returned as a
+    rectangle. If blend is true, the shades will be be blended with existing
+    pixel shades instead of overwriting them. This function accepts floating
+    point values for the end points. 
+    
+    :Parameters:
+        `surface` : `Surface`
+            Surface to draw on.
+        `color` : int, int, int
+            RGB fill color.
+        `start_pos` : float, float
+            X, Y coordinates of first vertex.
+        `end_pos` : float, float
+            X, Y coordinates of second vertex.
+        `width` : int
+            Line thickness.
+
+    :rtype: `Rect`
+    :return: Affected bounding box.
+    '''
+
+def aalines(surface, color, closed, pointlist, blend=1):
+    '''Draw multiple contiguous line segments with antialiasing.
+
+    Draws a sequence on a surface. You must pass at least two points in the
+    sequence of points. The closed argument is a simple boolean and if true, a
+    line will be draw between the first and last points. The boolean blend
+    argument set to true will blend the shades with existing shades instead of
+    overwriting them. This function accepts floating point values for the end
+    points. 
+
+    :Parameters:
+        `surface` : `Surface`
+            Surface to draw on.
+        `color` : int, int, int
+            RGB fill color.
+        `closed` : bool
+            True if line segments form a closed polygon, otherwise False.
+        `pointlist` : list of (float, float)
+            List of X, Y coordinates giving vertices.
+        `width` : int
+            Line thickness.
+
+    :rtype: `Rect`
+    :return: Affected bounding box.
+    '''
 
 import SDL.video
 
+class _RectProxy(object):
+    '''Proxy for SDL_Rect that can handle negative size.'''
+
+    __slots__ = ['x', 'y', 'w', 'h']
+
+    def __init__(self, r):
+        if isinstance(r, SDL.SDL_Rect) or isinstance(r, Rect):
+            self.x = r.x
+            self.y = r.y
+            self.w = r.w
+            self.h = r.h
+        else:
+            self.x = r[0]
+            self.y = r[1]
+            self.w = r[2]
+            self.h = r[3]
+
+    def _get_as_parameter_(self):
+        return SDL.SDL_Rect(self.x, self.y, self.w, self.h)
+
+    _as_parameter_ = property(_get_as_parameter_)
+
 class Rect(object):
-    '''
-    :note: Unlike previous versions of Pygame, pygame-ctypes does not
-        permit Rects with negative width or height, and initialising
-        one or setting the width, height or size attributes to be
-        negative will raise an exception.
-    '''
     __slots__ = ['_r']
 
     def __init__(self, *args):
                 raise TypeError, 'Argument must be rect style object'
         if len(args) == 4:
             if args[2] < 0 or args[3] < 0:
-                raise NotImplementedError, 'Negative sized rect not permitted'
-            object.__setattr__(self, '_r', SDL.SDL_Rect(int(args[0]),
-                                                        int(args[1]),
-                                                        int(args[2]),
-                                                        int(args[3])))
+                object.__setattr__(self, '_r', _RectProxy((int(args[0]),
+                                                          int(args[1]),
+                                                          int(args[2]),
+                                                          int(args[3]))))
+            else:
+                object.__setattr__(self, '_r', SDL.SDL_Rect(int(args[0]),
+                                                            int(args[1]),
+                                                            int(args[2]),
+                                                            int(args[3])))
         elif len(args) == 2:
             if args[1][0] < 0 or args[1][1] < 0:
-                raise NotImplementedError, 'Negative sized rect not permitted'
-            object.__setattr__(self, '_r', 
-                               SDL.SDL_Rect(int(args[0][0]), int(args[0][1]), 
-                                            int(args[1][0]), int(args[1][1])))
+                object.__setattr__(self, '_r', 
+                                   _RectProxy((int(args[0][0]), 
+                                              int(args[0][1]), 
+                                              int(args[1][0]), 
+                                              int(args[1][1]))))
+            else:
+                object.__setattr__(self, '_r', 
+                                   SDL.SDL_Rect(int(args[0][0]), 
+                                                int(args[0][1]), 
+                                                int(args[1][0]), 
+                                                int(args[1][1])))
         else:
             raise TypeError, 'Argument must be rect style object'
 
             self._r.y = value - self._r.h / 2
         elif name == 'size':
             if value[0] < 0 or value[1] < 0:
-                raise NotImplementedError, 'Negative sized rect not permitted'
+                self._ensure_proxy()
             self._r.w, self._r.h = value
         elif name == 'width':
             if value < 0:
-                raise NotImplementedError, 'Negative sized rect not permitted'
+                self._ensure_proxy()
             self._r.w = value
         elif name == 'height':
             if value < 0:
-                raise NotImplementedError, 'Negative sized rect not permitted'
+                self._ensure_proxy()
             self._r.h = value
         else:
             raise AttributeError, name
 
+    def _ensure_proxy(self):
+        if not isinstance(self._r, _RectProxy):
+            object.__setattr__(self, '_r', _RectProxy(self._r))
+
     def __len__(self):
         return 4
 
         self._r.y = other.y + (other.h - self._r.h) / 2
 
     def normalize(self):
-        # No-op, since negative width / height not permitted in pygame-ctypes.
         if self._r.w < 0:
             self._r.x += self._r.w
             self._r.w = -self._r.w