Code

Fix Bug #447385 - Drag'n'drop from swatches doesn't always work
[inkscape.git] / src / libnr / nr-pixblock.cpp
index 079bca6cab61fd5e64940e24f8f8d12bf34824b8..d69b6fe547eb96243f8f1bcfa74e5f2af75513ea 100644 (file)
@@ -5,10 +5,14 @@
  *
  * Authors:
  *   (C) 1999-2002 Lauris Kaplinski <lauris@kaplinski.com>
+ *   2008, Jasper van de Gronde <th.v.d.gonde@hccnet.nl>
  *
  * This code is in the Public Domain
  */
 
+#include <cstring>
+#include <string>
+#include <string.h>
 #include <glib/gmem.h>
 #include "nr-pixblock.h"
 
@@ -59,7 +63,18 @@ nr_pixblock_setup_fast (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, i
                pb->data.px = nr_pixelstore_1M_new (clear, 0x0);
        } else {
                pb->size = NR_PIXBLOCK_SIZE_BIG;
-               pb->data.px = g_new (unsigned char, size);
+             pb->data.px = NULL;
+               if (size > 100000000) { // Don't even try to allocate more than 100Mb (5000x5000 RGBA
+                            // pixels). It'll just bog the system down even if successful. FIXME:
+                            // Can anyone suggest something better than the magic number?
+                g_warning ("%lu bytes requested for pixel buffer, I won't try to allocate that.", (long unsigned) size);
+                return;
+             }
+               pb->data.px = g_try_new (unsigned char, size);
+               if (pb->data.px == NULL) { // memory allocation failed
+                g_warning ("Could not allocate %lu bytes for pixel buffer!", (long unsigned) size);
+                return;
+             }
                if (clear) memset (pb->data.px, 0x0, size);
        }
 
@@ -80,6 +95,7 @@ nr_pixblock_setup_fast (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, i
  * \param mode Indicates grayscale/RGB/RGBA.
  * \param clear True if buffer should be cleared.
  * \pre x1>=x0 && y1>=y0 && pb!=NULL
+ FIXME: currently unused except for nr_pixblock_new and pattern tiles, replace with _fast and delete?
  */
 void
 nr_pixblock_setup (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear)
@@ -198,6 +214,7 @@ nr_pixblock_release (NRPixBlock *pb)
  *
  * \return Pointer to fresh pixblock.
  * Calls g_new() and nr_pixblock_setup().
+FIXME: currently unused, delete? JG: Should be used more often! (To simplify memory management.)
  */
 NRPixBlock *
 nr_pixblock_new (NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear)
@@ -205,12 +222,40 @@ nr_pixblock_new (NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool cle
        NRPixBlock *pb;
 
        pb = g_new (NRPixBlock, 1);
+    if (!pb) return 0;
 
        nr_pixblock_setup (pb, mode, x0, y0, x1, y1, clear);
+    if (pb->size!=NR_PIXBLOCK_SIZE_TINY && !pb->data.px) {
+        g_free(pb);
+        return 0;
+    }
 
        return pb;
 }
 
+/**
+ * Allocates NRPixBlock and sets it up.
+ *
+ * \return Pointer to fresh pixblock.
+ * Calls g_new() and nr_pixblock_setup().
+ */
+NRPixBlock *
+nr_pixblock_new_fast (NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear)
+{
+    NRPixBlock *pb;
+
+    pb = g_new (NRPixBlock, 1);
+    if (!pb) return 0;
+
+    nr_pixblock_setup_fast (pb, mode, x0, y0, x1, y1, clear);
+    if (pb->size!=NR_PIXBLOCK_SIZE_TINY && !pb->data.px) {
+        g_free(pb);
+        return 0;
+    }
+
+    return pb;
+}
+
 /**
  * Frees all memory taken by pixblock.
  *
@@ -409,4 +454,4 @@ nr_pixelstore_1M_free (unsigned char *px)
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :