Code

Patch by Adib to fix 273767
[inkscape.git] / src / helper / pixbuf-ops.cpp
index ee5f72161db11313d812ae17f1b2fb7659b53890..1e43df5f38b804556cfec1bcd6398cb798781e53 100644 (file)
@@ -98,9 +98,10 @@ sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/,
 
 {
 
-
-     /* Create new arena */
+     GdkPixbuf* pixbuf = NULL;
+     /* Create new arena for offscreen rendering*/
      NRArena *arena = NRArena::create();
+     nr_arena_set_renderoffscreen(arena);
      unsigned dkey = sp_item_display_key_new(1);
 
      sp_document_ensure_up_to_date (doc);
@@ -123,7 +124,7 @@ sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/,
      nr_arena_item_set_transform(NR_ARENA_ITEM(root), affine);
 
      NRGC gc(NULL);
-     gc.transform.set_identity();
+     gc.transform.setIdentity();
 
      // We show all and then hide all items we don't want, instead of showing only requested items,
      // because that would not work if the shown item references something in defs
@@ -139,36 +140,50 @@ sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/,
 
      nr_arena_item_invoke_update(root, &final_bbox, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
 
-     guchar *px = g_new(guchar, 4 * width * height);
-
-     NRPixBlock B;
-     nr_pixblock_setup_extern( &B, NR_PIXBLOCK_MODE_R8G8B8A8N,
-                               final_bbox.x0, final_bbox.y0, final_bbox.x1, final_bbox.y1,
-                               px, 4 * width, FALSE, FALSE );
+    guchar *px = NULL;
+    guint64 size = 4L * (guint64)width * (guint64)height;
+    if(size < (guint64)G_MAXSIZE) {
+        // g_try_new is limited to g_size type which is defined as unisgned int. Need to test for very large nubers
+        px = g_try_new(guchar, size);
+    }
 
-     unsigned char dtc[4];
-     dtc[0] = NR_RGBA32_R(bgcolor);
-     dtc[1] = NR_RGBA32_G(bgcolor);
-     dtc[2] = NR_RGBA32_B(bgcolor);
-     dtc[3] = NR_RGBA32_A(bgcolor);
+    if(px != NULL)
+    {
 
-     for (unsigned int fy = 0; fy < height; fy++) {
-         guchar *p = NR_PIXBLOCK_PX(&B) + fy * B.rs;
-         for (unsigned int fx = 0; fx < width; fx++) {
-             for (int i = 0; i < 4; i++) {
-                 *p++ = dtc[i];
+         NRPixBlock B;
+         //g_warning("sp_generate_internal_bitmap: nr_pixblock_setup_extern.");
+         nr_pixblock_setup_extern( &B, NR_PIXBLOCK_MODE_R8G8B8A8N,
+                                   final_bbox.x0, final_bbox.y0, final_bbox.x1, final_bbox.y1,
+                                   px, 4 * width, FALSE, FALSE );
+
+         unsigned char dtc[4];
+         dtc[0] = NR_RGBA32_R(bgcolor);
+         dtc[1] = NR_RGBA32_G(bgcolor);
+         dtc[2] = NR_RGBA32_B(bgcolor);
+         dtc[3] = NR_RGBA32_A(bgcolor);
+
+         for (gsize fy = 0; fy < height; fy++) {
+             guchar *p = NR_PIXBLOCK_PX(&B) + fy * (gsize)B.rs;
+             for (unsigned int fx = 0; fx < width; fx++) {
+                 for (int i = 0; i < 4; i++) {
+                     *p++ = dtc[i];
+                 }
              }
          }
-     }
 
-     nr_arena_item_invoke_render(NULL, root, &final_bbox, &B, NR_ARENA_ITEM_RENDER_NO_CACHE );
 
-     GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(px, GDK_COLORSPACE_RGB,
-                                          TRUE,
-                                          8, width, height, width * 4,
-                                          (GdkPixbufDestroyNotify)g_free,
-                                          NULL);
+         nr_arena_item_invoke_render(NULL, root, &final_bbox, &B, NR_ARENA_ITEM_RENDER_NO_CACHE );
 
+         pixbuf = gdk_pixbuf_new_from_data(px, GDK_COLORSPACE_RGB,
+                                              TRUE,
+                                              8, width, height, width * 4,
+                                              (GdkPixbufDestroyNotify)g_free,
+                                              NULL);
+    }
+    else
+    {
+        g_warning("sp_generate_internal_bitmap: not enough memory to create pixel buffer. Need %lld.", size);
+    }
      sp_item_invoke_hide (SP_ITEM(sp_document_root(doc)), dkey);
      nr_object_unref((NRObject *) arena);