Commits

Anonymous committed de465dc

Merged with trunk rev 2383

Comments (0)

Files changed (12)

 # SVN revision numbers, and CVS tag names are placed before the date
 # BREAK = change breaks existing code
 # BUG    = fixed a bug that was (or could have been) crashing
-#
-#
+
+[SVN 2380-2381] Jun 19, 2009
+    Color.set_length method... to change Color length to 1,2,3 or 4.
+    Surface.get_palette(_at) return Color with length 3.
 
 [SVN 2366] Jun 17, 2009
     [BUG] Memory leak in a few modules.  Thanks Lorenz Quack.

docs/ref/color.html

   <tr><td><a href="color.html#Color.i1i2i3">Color.i1i2i3</a> - <font size=-1>Gets or sets the I1I2I3 representation of the Color.</font></td><td>Gets or sets the I1I2I3 representation of the Color.</td></tr>
   <tr><td><a href="color.html#Color.normalize">Color.normalize</a> - <font size=-1>Returns the normalized RGBA values of the Color.</font></td><td>Returns the normalized RGBA values of the Color.</td></tr>
   <tr><td><a href="color.html#Color.correct_gamma">Color.correct_gamma</a> - <font size=-1>Applies a certain gamma value to the Color.</font></td><td>Applies a certain gamma value to the Color.</td></tr>
+  <tr><td><a href="color.html#Color.set_length">Color.set_length</a> - <font size=-1>Set the number of elements in the Color to 1,2,3, or 4.</font></td><td>Set the number of elements in the Color to 1,2,3, or 4.</td></tr>
 </table></small></ul>
 <p>The Color class represents <tt>RGBA</tt> color values using a value range of 0-255. It allows basic arithmetic operations to create new colors, supports conversions to other color spaces such as <tt>HSV</tt> or <tt>HSL</tt> and lets you adjust single color channels. Alpha defaults to 255 when not given. </p>
 <p>'rgbvalue' can be either a color name, an <tt>HTML</tt> color format string, a hex number string, or an integer pixel value. The <tt>HTML</tt> format is '#rrggbbaa', where rr, gg, bb, and aa are 2 digit hex numbers. The alpha aa is optional. <tt>A</tt> hex number string has the form '0xrrggbbaa', where aa is optional. </p>
-<p>Color objects support equality comparison with other color objects and 3 or 4 element tuples of integers (New in <tt>1.9.0)</tt>. </p>
-<p>New in pygame <tt>1.8.1</tt>. </p>
+<p>Color objects support equality comparison with other color objects and 3 or 4 element tuples of integers (New in <tt>1.9.0)</tt>. There was a bug in pygame <tt>1.8.1</tt> where the default alpha was 0, not 255 like previously. </p>
+<p>New implementation of Color was done in pygame <tt>1.8.1</tt>. </p>
 <!--COMMENTS:pygame.Color--> &nbsp;<br> 
 
 
 <p>Applies a certain gamma value to the Color and returns a new Color with the adjusted <tt>RGBA</tt> values. </p>
 <!--COMMENTS:Color.correct_gamma--> &nbsp;<br> 
 <br></ul>
+
+
+<a name="Color.set_length">
+<big><b>Color.set_length</big></b><br><ul>
+  <i>Set the number of elements in the Color to 1,2,3, or 4.</i><br>
+  <tt>Color.set_length(len)</tt><br>
+<p>The default Color length is 4. Colors can have lengths 1,2,3 or 4. This is useful if you want to unpack to r,g,b and not r,g,b,a. If you want to get the length of a Color do len(acolor). </p>
+<p>New in pygame <tt>1.9.0</tt>. </p>
+<!--COMMENTS:Color.set_length--> &nbsp;<br> 
+<br></ul>
 <br></ul>
 
 </body></html>

docs/ref/index.html

 <li><a href="color.html#Color.i1i2i3">Color.i1i2i3</a> - <font size=-1>Gets or sets the I1I2I3 representation of the Color.</font></li>
 <li><a href="color.html#Color.normalize">Color.normalize</a> - <font size=-1>Returns the normalized RGBA values of the Color.</font></li>
 <li><a href="color.html#Color.r">Color.r</a> - <font size=-1>Gets or sets the red value of the Color.</font></li>
+<li><a href="color.html#Color.set_length">Color.set_length</a> - <font size=-1>Set the number of elements in the Color to 1,2,3, or 4.</font></li>
 </ul>
 <li><a href="overlay.html#pygame.Overlay">pygame.Overlay</a> - <font size=-1>pygame object for video overlay graphics</font></li>
 <ul>

docs/ref/surface.html

 <big><b>Surface.get_at</big></b><br><ul>
   <i>get the color value at a single pixel</i><br>
   <tt>Surface.get_at((x, y)): return Color</tt><br>
-<p>Return the <tt>RGBA</tt> color value at the given pixel. If the Surface has no per pixel alpha, then the alpha value will always be 255 (opaque). If the pixel position is outside the area of the Surface an IndexError exception will be raised. </p>
-<p>Getting and setting pixels one at a time is generally too slow to be used in a game or realtime situation. </p>
+<p>Return a copy of the <tt>RGBA</tt> Color value at the given pixel. If the Surface has no per pixel alpha, then the alpha value will always be 255 (opaque). If the pixel position is outside the area of the Surface an IndexError exception will be raised. </p>
+<p>Getting and setting pixels one at a time is generally too slow to be used in a game or realtime situation. It is better to use methods which operate on many pixels at a time like with the blit, fill and draw methods - or by using surfarray/PixelArray. </p>
 <p>This function will temporarily lock and unlock the Surface as needed. </p>
 <p>Returning a Color instead of tuple, New in pygame <tt>1.9.0</tt>. Use <tt>tuple(surf.get_at((x,y)))</tt> if you want a tuple, and not a Color. This should only matter if you want to use the color as a key in a dict. </p>
 <!--COMMENTS:Surface.get_at--> &nbsp;<br> 
   <i>get the color index palette for an 8bit Surface</i><br>
   <tt>Surface.get_palette(): return [RGB, RGB, RGB, ...]</tt><br>
 <p>Return a list of up to 256 color elements that represent the indexed colors used in an 8bit Surface. The returned list is a copy of the palette, and changes will have no effect on the Surface. </p>
-<p>Returning a list of Color instances instead of tuples, New in pygame <tt>1.9.0</tt> </p>
+<p>Returning a list of Color(with length 3) instances instead of tuples, New in pygame <tt>1.9.0</tt> </p>
 <!--COMMENTS:Surface.get_palette--> &nbsp;<br> 
 <br></ul>
 
   <i>get the color for a single entry in a palette</i><br>
   <tt>Surface.get_palette_at(index): return RGB</tt><br>
 <p>Returns the red, green, and blue color values for a single index in a Surface palette. The index should be a value from 0 to 255. </p>
-<p>Returning Color instance instead of a tuple, New in pygame <tt>1.9.0</tt> </p>
+<p>Returning Color(with length 3) instance instead of a tuple, New in pygame <tt>1.9.0</tt> </p>
 <!--COMMENTS:Surface.get_palette_at--> &nbsp;<br> 
 <br></ul>
 
     Uint8 g;
     Uint8 b;
     Uint8 a;
+    Uint8 len;
 } PyColor;
 
 typedef enum {
 static int _coerce_obj(PyObject *obj, Uint8 rgba[]);
 
 static PyColor* _color_new_internal (PyTypeObject *type, Uint8 rgba[]);
+static PyColor* _color_new_internal_length (PyTypeObject *type, Uint8 rgba[], Uint8 length);
+
 static PyObject* _color_new (PyTypeObject *type, PyObject *args,
     PyObject *kwds);
 static void _color_dealloc (PyColor *color);
 static PyObject* _color_repr (PyColor *color);
 static PyObject* _color_normalize (PyColor *color);
 static PyObject* _color_correct_gamma (PyColor *color, PyObject *args);
+static PyObject* _color_set_length (PyColor *color, PyObject *args);
 
 /* Getters/setters */
 static PyObject* _color_get_r (PyColor *color, void *closure);
 
 /* C API interfaces */
 static PyObject* PyColor_New (Uint8 rgba[]);
+static PyObject* PyColor_NewLength (Uint8 rgba[], Uint8 length);
 static int RGBAFromColorObj (PyObject *color, Uint8 rgba[]);
 
 /**
       DOC_COLORNORMALIZE },
     { "correct_gamma", (PyCFunction) _color_correct_gamma, METH_VARARGS,
       DOC_COLORCORRECTGAMMA },
+    { "set_length", (PyCFunction) _color_set_length, METH_VARARGS,
+      DOC_COLORSETLENGTH },
     { NULL, NULL, 0, NULL }
 };
 
 static PyColor*
 _color_new_internal (PyTypeObject *type, Uint8 rgba[])
 {
+    /* default length of 4 - r,g,b,a. */
+    return _color_new_internal_length(type, rgba, 4);
+}
+
+
+static PyColor*
+_color_new_internal_length (PyTypeObject *type, Uint8 rgba[], Uint8 length)
+{
     PyColor *color = (PyColor *) type->tp_alloc (type, 0);
     if (!color)
         return NULL;
     color->g = rgba[1];
     color->b = rgba[2];
     color->a = rgba[3];
+    color->len = length;
 
     return color;
 }
 
-
-
 /**
  * Creates a new PyColor.
  */
 static Py_ssize_t
 _color_length (PyColor *color)
 {
-    return 4;
+    return color->len;
 }
 
 /**
+ * color.set_length(3)
+ */
+
+static PyObject*
+_color_set_length (PyColor *color, PyObject *args)
+{
+    Py_ssize_t clength;
+
+    if (!PyArg_ParseTuple (args, "k", &clength))
+        return NULL;
+
+    if (clength > 4 || clength < 1) {
+        return RAISE (PyExc_ValueError, "Length needs to be 1,2,3, or 4.");
+    }
+
+    color->len = clength;
+
+    Py_RETURN_NONE;
+}
+
+
+
+
+/**
  * color[x]
  */
 static PyObject*
 _color_item (PyColor *color, Py_ssize_t _index)
 {
+
+    if((_index > (color->len-1)) ) {
+        return RAISE (PyExc_IndexError, "invalid index");
+    }
+
     switch (_index)
     {
     case 0:
 static int
 _color_ass_item (PyColor *color, Py_ssize_t _index, PyObject *value)
 {
+
     switch (_index)
     {
     case 0:
     return (PyObject *) _color_new_internal (&PyColor_Type, rgba);
 }
 
+static PyObject*
+PyColor_NewLength (Uint8 rgba[], Uint8 length)
+{
+    if(length < 1 || length > 4) {
+        return NULL;
+    }
+
+    return (PyObject *) _color_new_internal_length (&PyColor_Type, rgba, length);
+}
+
+
+
+
 static int
 RGBAFromColorObj (PyObject *color, Uint8 rgba[])
 {
     c_api[0] = &PyColor_Type;
     c_api[1] = PyColor_New;
     c_api[2] = RGBAFromColorObj;
+    c_api[3] = PyColor_NewLength;
 
     apiobj = PyCObject_FromVoidPtr (c_api, NULL);
     if (apiobj == NULL) {
 where aa is optional.
 
 Color objects support equality comparison with other color objects
-and 3 or 4 element tuples of integers (New in 1.9.0).
+and 3 or 4 element tuples of integers (New in 1.9.0).  There was a bug in
+pygame 1.8.1 where the default alpha was 0, not 255 like previously.
 
-New in pygame 1.8.1.
+New implementation of Color was done in pygame 1.8.1.
 <SECTION>
 
+
+
 r
 Gets or sets the red value of the Color.
 Color.r: Return int
 The red value of the Color.
 <END>
 
+
+
 g
 Gets or sets the green value of the Color.
 Color.g: Return int
 The green value of the Color.
 <END>
 
+
+
 b
 Gets or sets the blue value of the Color.
 Color.b: Return int
 The blue value of the Color.
 <END>
 
+
+
 a
 Gets or sets the alpha value of the Color.
 Color.a: Return int
 The alpha value of the Color.
 <END>
 
+
+
 cmy
 Gets or sets the CMY representation of the Color.
 Color.cmy: Return tuple
 you might expect.
 <END>
 
+
+
 hsva
 Gets or sets the HSVA representation of the Color.
 Color.hsva: Return tuple
 differ slightly from what you might expect.
 <END>
 
+
+
 hsla
 Gets or sets the HSLA representation of the Color.
 Color.hsla: Return tuple
 differ slightly from what you might expect.
 <END>
 
+
+
 i1i2i3
 Gets or sets the I1I2I3 representation of the Color.
 Color.i1i2i3: Return tuple
 slightly from what you might expect.
 <END>
 
+
+
 normalize
 Returns the normalized RGBA values of the Color.
 Color.normalize(): Return tuple
 values.
 <END>
 
+
+
 correct_gamma
 Applies a certain gamma value to the Color.
 Color.correct_gamma (gamma): Return Color
 Applies a certain gamma value to the Color and returns a new Color with
 the adjusted RGBA values.
 <END>
+
+
+
+set_length
+Set the number of elements in the Color to 1,2,3, or 4.
+Color.set_length(len)
+
+The default Color length is 4.  Colors can have lengths 1,2,3 or 4.
+This is useful if you want to unpack to r,g,b and not r,g,b,a.
+If you want to get the length of a Color do len(acolor).
+
+New in pygame 1.9.0.
+<END>
 /* Color */
 #define PYGAMEAPI_COLOR_FIRSTSLOT                                       \
     (PYGAMEAPI_PIXELARRAY_FIRSTSLOT + PYGAMEAPI_PIXELARRAY_NUMSLOTS)
-#define PYGAMEAPI_COLOR_NUMSLOTS 3
+#define PYGAMEAPI_COLOR_NUMSLOTS 4
 #ifndef PYGAMEAPI_COLOR_INTERNAL
 #define PyColor_Check(x)                                                \
     ((x)->ob_type == (PyTypeObject*)                                    \
         PyGAME_C_API[PYGAMEAPI_COLOR_FIRSTSLOT + 0])
 #define PyColor_New                                                     \
     (*(PyObject *(*)(Uint8*)) PyGAME_C_API[PYGAMEAPI_COLOR_FIRSTSLOT + 1])
+#define PyColor_NewLength                                               \
+    (*(PyObject *(*)(Uint8*, Uint8)) PyGAME_C_API[PYGAMEAPI_COLOR_FIRSTSLOT + 3])
+
 #define RGBAFromColorObj                                                \
     (*(int(*)(PyObject*, Uint8*)) PyGAME_C_API[PYGAMEAPI_COLOR_FIRSTSLOT + 2])
 #define import_pygame_color()                                           \
 
 #define DOC_COLORCORRECTGAMMA "Color.correct_gamma (gamma): Return Color\nApplies a certain gamma value to the Color."
 
+#define DOC_COLORSETLENGTH "Color.set_length(len)\nSet the number of elements in the Color to 1,2,3, or 4."
+
 #define DOC_PYGAMECURSORS "pygame module for cursor resources"
 
 #define DOC_PYGAMECURSORSCOMPILE "pygame.cursor.compile(strings, black='X', white='.', xor='o'): return data, mask\ncreate binary cursor data from simple strings"
 
 
 
+Color.set_length
+ Color.set_length(len)
+Set the number of elements in the Color to 1,2,3, or 4.
+
+
+
 pygame.cursors
  pygame module for cursor resources
 
         rgba[0] = c->r;
         rgba[1] = c->g;
         rgba[2] = c->b;
-        color = PyColor_New (rgba);
+        color = PyColor_NewLength (rgba, 3);
+
         if (!color)
         {
             Py_DECREF (list);
     rgba[1] = c->g;
     rgba[2] = c->b;
     rgba[3] = 255;
-    return PyColor_New (rgba);
+
+    return PyColor_NewLength (rgba, 3);
 }
 
 static PyObject*
 used in an 8bit Surface. The returned list is a copy of the palette, and 
 changes will have no effect on the Surface.
 
-Returning a list of Color instances instead of tuples, New in pygame 1.9.0
+Returning a list of Color(with length 3) instances instead of tuples, New in pygame 1.9.0
 <END>
 
 
 Returns the red, green, and blue color values for a single index in a Surface
 palette. The index should be a value from 0 to 255.
 
-Returning Color instance instead of a tuple, New in pygame 1.9.0
+Returning Color(with length 3) instance instead of a tuple, New in pygame 1.9.0
 <END>
 
 

test/color_test.py

         # NOTE: assigning to a slice is currently unsupported.
         
         
+    def test_unpack(self):
+        # should be able to unpack to r,g,b,a and r,g,b
+        c = pygame.Color(1,2,3,4)
+        r,g,b,a = c
+        self.assertEquals((1,2,3,4), (r,g,b,a))
+        self.assertEquals(c, (r,g,b,a))
+        
+        c.set_length(3)
+        r,g,b = c
+        self.assertEquals((1,2,3), (r,g,b))
+
+
+
+        
+
+
+    def test_length(self):
+        # should be able to unpack to r,g,b,a and r,g,b
+        c = pygame.Color(1,2,3,4)
+        self.assertEquals(len(c), 4)
+
+        c.set_length(3)
+        self.assertEquals(len(c), 3)
+
+        # it keeps the old alpha anyway...
+        self.assertEquals(c.a, 4)
+
+        # however you can't get the alpha in this way:
+        self.assertRaises (IndexError, lambda x:c[x], 4)
+
+
+
+        c.set_length(4)
+        self.assertEquals(len(c), 4)
+        self.assertEquals(len(c), 4)
+
+        self.assertRaises (ValueError, c.set_length, 5)
+        self.assertRaises (ValueError, c.set_length, -1)
+        self.assertRaises (ValueError, c.set_length, 0)
+        self.assertRaises (ValueError, c.set_length, pow(2,33L))
         
         
     def test_case_insensitivity_of_string_args(self):

test/surface_test.py

             surf = pygame.Surface((2, 2), 0, 8)
             surf.set_palette(palette)
             palette2 = surf.get_palette()
+            r,g,b = palette2[0]
+
             self.failUnlessEqual(len(palette2), len(palette))
             for c2, c in zip(palette2, palette):
                 self.failUnlessEqual(c2, c)