Code

Merge and cleanup of GSoC C++-ification project.
[inkscape.git] / src / helper / pixbuf-ops.cpp
index f44a514a1e4b69ffe89a88f1be04d468c3e92364..69becad5dd421f83ed7a8bcad092680acd801045 100644 (file)
@@ -1,10 +1,10 @@
-#define __SP_PIXBUF_OPS_C__
-
 /*
  * Helpers for SPItem -> gdk_pixbuf related stuff
  *
  * Authors:
  *   John Cliff <simarilius@yahoo.com>
+ *   Jon A. Cruz <jon@joncruz.org>
+ *   Abhishek Sharma
  *
  * Copyright (C) 2008 John Cliff
  *
@@ -26,7 +26,9 @@
 #include <document.h>
 #include <sp-item.h>
 #include <sp-root.h>
+#include <sp-use.h>
 #include <sp-defs.h>
+#include "unit-constants.h"
 
 #include "libnr/nr-matrix-translate-ops.h"
 #include "libnr/nr-scale-ops.h"
 
 #include "pixbuf-ops.h"
 
+// TODO look for copy-n-past duplication of this function:
 /**
  * Hide all items that are not listed in list, recursively, skipping groups and defs.
  */
-static void
-hide_other_items_recursively(SPObject *o, GSList *list, unsigned dkey)
+static void hide_other_items_recursively(SPObject *o, GSList *list, unsigned dkey)
 {
     if ( SP_IS_ITEM(o)
          && !SP_IS_DEFS(o)
          && !SP_IS_ROOT(o)
          && !SP_IS_GROUP(o)
+         && !SP_IS_USE(o)
          && !g_slist_find(list, o) )
     {
-        sp_item_invoke_hide(SP_ITEM(o), dkey);
+        SP_ITEM(o)->invoke_hide(dkey);
     }
 
     // recurse
     if (!g_slist_find(list, o)) {
-        for (SPObject *child = sp_object_first_child(o) ; child != NULL; child = SP_OBJECT_NEXT(child) ) {
+        for ( SPObject *child = o->firstChild() ; child; child = child->getNext() ) {
             hide_other_items_recursively(child, list, dkey);
         }
     }
@@ -83,6 +86,7 @@ sp_export_jpg_file(SPDocument *doc, gchar const *filename,
      g_snprintf(c, 32, "%f", quality);
      gboolean saved = gdk_pixbuf_save (pixbuf, filename, "jpeg", NULL, "quality", c, NULL);
      g_free(c);
+     gdk_pixbuf_unref (pixbuf);
      if (saved) return true;
      else return false;
 }
@@ -90,47 +94,44 @@ sp_export_jpg_file(SPDocument *doc, gchar const *filename,
 GdkPixbuf*
 sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/,
                             double x0, double y0, double x1, double y1,
-                            unsigned width, unsigned height, double /*xdpi*/, double /*ydpi*/,
+                            unsigned width, unsigned height, double xdpi, double ydpi,
                             unsigned long bgcolor,
                             GSList *items_only)
 
 {
 
-
-     /* Create new arena */
+     GdkPixbuf* pixbuf = NULL;
+     /* Create new arena for offscreen rendering*/
      NRArena *arena = NRArena::create();
-     unsigned dkey = sp_item_display_key_new(1);
+     nr_arena_set_renderoffscreen(arena);
+     unsigned dkey = SPItem::display_key_new(1);
 
-     sp_document_ensure_up_to_date (doc);
+     doc->ensureUpToDate();
 
-     NR::Rect screen=NR::Rect(NR::Point(x0,y0), NR::Point(x1, y1));
+     Geom::Rect screen=Geom::Rect(Geom::Point(x0,y0), Geom::Point(x1, y1));
 
-     double zoom_scale = 1.0;
      double padding = 1.0;
 
-     width = (int)ceil(screen.extent(NR::X) * zoom_scale * padding);
-     height = (int)ceil(screen.extent(NR::Y) * zoom_scale * padding);
-
-     NR::Point origin(screen.min()[NR::X],
-                      sp_document_height(doc) - screen.extent(NR::Y) - screen.min()[NR::Y]);
+     Geom::Point origin(screen.min()[Geom::X],
+                      doc->getHeight() - screen[Geom::Y].extent() - screen.min()[Geom::Y]);
 
-     origin[NR::X] = origin[NR::X] + (screen.extent(NR::X) * ((1 - padding) / 2));
-     origin[NR::Y] = origin[NR::Y] + (screen.extent(NR::Y) * ((1 - padding) / 2));
+     origin[Geom::X] = origin[Geom::X] + (screen[Geom::X].extent() * ((1 - padding) / 2));
+     origin[Geom::Y] = origin[Geom::Y] + (screen[Geom::Y].extent() * ((1 - padding) / 2));
 
-     NR::scale scale(zoom_scale, zoom_scale);
-     NR::Matrix affine = scale * NR::translate(-origin * scale);
+     Geom::Scale scale( (xdpi / PX_PER_IN),   (ydpi / PX_PER_IN));
+     Geom::Matrix affine = scale * Geom::Translate(-origin * scale);
 
      /* Create ArenaItems and set transform */
-     NRArenaItem *root = sp_item_invoke_show(SP_ITEM(sp_document_root(doc)), arena, dkey, SP_ITEM_SHOW_DISPLAY);
+     NRArenaItem *root = SP_ITEM(doc->getRoot())->invoke_show( arena, dkey, SP_ITEM_SHOW_DISPLAY);
      nr_arena_item_set_transform(NR_ARENA_ITEM(root), affine);
 
      NRGC gc(NULL);
-     nr_matrix_set_identity(&gc.transform);
+     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
      if (items_only) {
-         hide_other_items_recursively(sp_document_root(doc), items_only, dkey);
+         hide_other_items_recursively(doc->getRoot(), items_only, dkey);
      }
 
      NRRectL final_bbox;
@@ -141,35 +142,52 @@ 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(doc->getRoot())->invoke_hide(dkey);
+     nr_object_unref((NRObject *) arena);
 
 //    gdk_pixbuf_save (pixbuf, "C:\\temp\\internal.jpg", "jpeg", NULL, "quality","100", NULL);
 
@@ -185,4 +203,4 @@ sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/,
   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 :