2008-06-23 Emmanuele Bassi <ebassi@openedhand.com>
authorEmmanuele Bassi <ebassi@openedhand.com>
Mon, 23 Jun 2008 10:06:02 +0000 (10:06 +0000)
committerEmmanuele Bassi <ebassi@openedhand.com>
Mon, 23 Jun 2008 10:06:02 +0000 (10:06 +0000)
Bug 981 - clutter_stage_read_pixels temprow fix (Haakon Sporsheim)

* clutter/clutter-stage.c (clutter_stage_read_pixels): Allocate
the temporary row data used to flip the buffer from glReadPixels()
in order to fix compilation under MSVC. Also validate the input
parameters to avoid random segfaults.

ChangeLog
clutter/clutter-stage.c

index 6d4e868..bf58b0d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2008-06-23  Emmanuele Bassi  <ebassi@openedhand.com>
+
+       Bug 981 - clutter_stage_read_pixels temprow fix (Haakon Sporsheim)
+
+       * clutter/clutter-stage.c (clutter_stage_read_pixels): Allocate
+       the temporary row data used to flip the buffer from glReadPixels()
+       in order to fix compilation under MSVC. Also validate the input
+       parameters to avoid random segfaults.
+
 2008-06-23  Matthew Allum  <mallum@openedhand.com>
 
        * clutter/clutter-actor.c:
index 781c0be..ba233a7 100644 (file)
@@ -1085,11 +1085,11 @@ clutter_stage_hide_cursor (ClutterStage *stage)
  *   entire stage height
  *
  * Makes a screenshot of the stage in RGBA 8bit data, returns a
- * linear buffer with @width*4 as rowstride.
- * Gets a pixel based representation of the current rendered stage.
+ * linear buffer with @width * 4 as rowstride.
  *
  * Return value: a pointer to newly allocated memory with the buffer
- * that should be free with g_free, or NULL if the read back failed.
+ *   or %NULL if the read failed. Use g_free() on the returned data
+ *   to release the resources it has allocated.
  */
 guchar *
 clutter_stage_read_pixels (ClutterStage *stage,
@@ -1099,6 +1099,7 @@ clutter_stage_read_pixels (ClutterStage *stage,
                            gint          height)
 {
   guchar *pixels;
+  guchar *temprow;
   GLint   viewport[4];
   gint    rowstride;
   gint    stage_x, stage_y, stage_width, stage_height;
@@ -1117,31 +1118,40 @@ clutter_stage_read_pixels (ClutterStage *stage,
   glGetIntegerv (GL_VIEWPORT, viewport);
   stage_x      = viewport[0];
   stage_y      = viewport[1];
-  stage_width  = viewport[2] - x;
-  stage_height = viewport[3] - y;
-  rowstride    = width * 4;
+  stage_width  = viewport[2];
+  stage_height = viewport[3];
 
-  pixels = g_malloc (height * rowstride);
+  if (width < 0 || width > stage_width)
+    width = stage_width;
+
+  if (height < 0 || height > stage_height)
+    height = stage_height;
+
+  rowstride = width * 4;
+
+  pixels  = g_malloc (height * rowstride);
+  temprow = g_malloc (rowstride);
 
   /* check whether we need to read into a smaller temporary buffer */
   glReadPixels (x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
 
   /* vertically flip the buffer in-place */
-  for (y=0; y< height/2; y++)
+  for (y = 0; y < height / 2; y++)
     {
-      guchar temprow[rowstride];
-      if (y != height-y-1) /* skip center row */
+      if (y != height - y - 1) /* skip center row */
         {
           memcpy (temprow,
                   pixels + y * rowstride, rowstride);
           memcpy (pixels + y * rowstride, 
-                  pixels + (height-y-1) * rowstride, rowstride);
-          memcpy (pixels + (height-y-1) * rowstride,
+                  pixels + (height - y - 1) * rowstride, rowstride);
+          memcpy (pixels + (height - y - 1) * rowstride,
                   temprow,
                   rowstride);
         }
     }
 
+  g_free (temprow);
+
   return pixels;
 }