Code

src/helper 2geomified
[inkscape.git] / src / helper / pixbuf-ops.cpp
1 #define __SP_PIXBUF_OPS_C__
3 /*
4  * Helpers for SPItem -> gdk_pixbuf related stuff
5  *
6  * Authors:
7  *   John Cliff <simarilius@yahoo.com>
8  *
9  * Copyright (C) 2008 John Cliff
10  *
11  * Released under GNU GPL, read the file 'COPYING' for more information
12  */
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #endif
18 #include <interface.h>
19 #include <libnr/nr-pixops.h>
20 #include <glib.h>
21 #include <glib/gmessages.h>
22 #include <png.h>
23 #include "png-write.h"
24 #include <display/nr-arena-item.h>
25 #include <display/nr-arena.h>
26 #include <document.h>
27 #include <sp-item.h>
28 #include <sp-root.h>
29 #include <sp-defs.h>
31 #include "libnr/nr-matrix-translate-ops.h"
32 #include "libnr/nr-scale-ops.h"
33 #include "libnr/nr-scale-translate-ops.h"
34 #include "libnr/nr-translate-matrix-ops.h"
35 #include "libnr/nr-translate-scale-ops.h"
37 #include "pixbuf-ops.h"
39 /**
40  * Hide all items that are not listed in list, recursively, skipping groups and defs.
41  */
42 static void
43 hide_other_items_recursively(SPObject *o, GSList *list, unsigned dkey)
44 {
45     if ( SP_IS_ITEM(o)
46          && !SP_IS_DEFS(o)
47          && !SP_IS_ROOT(o)
48          && !SP_IS_GROUP(o)
49          && !g_slist_find(list, o) )
50     {
51         sp_item_invoke_hide(SP_ITEM(o), dkey);
52     }
54     // recurse
55     if (!g_slist_find(list, o)) {
56         for (SPObject *child = sp_object_first_child(o) ; child != NULL; child = SP_OBJECT_NEXT(child) ) {
57             hide_other_items_recursively(child, list, dkey);
58         }
59     }
60 }
63 // The following is a mutation of the flood fill code, the marker preview, and random other samplings.
64 // The dpi settings dont do anything yet, but I want them to, and was wanting to keep reasonably close
65 // to the call for the interface to the png writing.
67 bool
68 sp_export_jpg_file(SPDocument *doc, gchar const *filename,
69                    double x0, double y0, double x1, double y1,
70                    unsigned width, unsigned height, double xdpi, double ydpi,
71                    unsigned long bgcolor, double quality,GSList *items)
73 {
76       GdkPixbuf* pixbuf;
77       pixbuf = sp_generate_internal_bitmap(doc, filename, x0, y0, x1, y1,
78                                          width, height, xdpi, ydpi,
79                                          bgcolor, items );
82      gchar c[32];
83      g_snprintf(c, 32, "%f", quality);
84      gboolean saved = gdk_pixbuf_save (pixbuf, filename, "jpeg", NULL, "quality", c, NULL);
85      g_free(c);
86      if (saved) return true;
87      else return false;
88 }
90 GdkPixbuf*
91 sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/,
92                             double x0, double y0, double x1, double y1,
93                             unsigned width, unsigned height, double /*xdpi*/, double /*ydpi*/,
94                             unsigned long bgcolor,
95                             GSList *items_only)
97 {
100      /* Create new arena */
101      NRArena *arena = NRArena::create();
102      unsigned dkey = sp_item_display_key_new(1);
104      sp_document_ensure_up_to_date (doc);
106      Geom::Rect screen=Geom::Rect(Geom::Point(x0,y0), Geom::Point(x1, y1));
108      double zoom_scale = 1.0;
109      double padding = 1.0;
111      width = (int)ceil(screen[Geom::X].extent() * zoom_scale * padding);
112      height = (int)ceil(screen[Geom::Y].extent() * zoom_scale * padding);
114      Geom::Point origin(screen.min()[Geom::X],
115                       sp_document_height(doc) - screen[Geom::Y].extent() - screen.min()[Geom::Y]);
117      origin[Geom::X] = origin[Geom::X] + (screen[Geom::X].extent() * ((1 - padding) / 2));
118      origin[Geom::Y] = origin[Geom::Y] + (screen[Geom::Y].extent() * ((1 - padding) / 2));
120      Geom::Scale scale(zoom_scale, zoom_scale);
121      Geom::Matrix affine = scale * Geom::Translate(-origin * scale);
123      /* Create ArenaItems and set transform */
124      NRArenaItem *root = sp_item_invoke_show(SP_ITEM(sp_document_root(doc)), arena, dkey, SP_ITEM_SHOW_DISPLAY);
125      nr_arena_item_set_transform(NR_ARENA_ITEM(root), from_2geom(affine));
127      NRGC gc(NULL);
128      gc.transform.set_identity();
130      // We show all and then hide all items we don't want, instead of showing only requested items,
131      // because that would not work if the shown item references something in defs
132      if (items_only) {
133          hide_other_items_recursively(sp_document_root(doc), items_only, dkey);
134      }
136      NRRectL final_bbox;
137      final_bbox.x0 = 0;
138      final_bbox.y0 = 0;//row;
139      final_bbox.x1 = width;
140      final_bbox.y1 = height;//row + num_rows;
142      nr_arena_item_invoke_update(root, &final_bbox, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
144      guchar *px = g_new(guchar, 4 * width * height);
146      NRPixBlock B;
147      nr_pixblock_setup_extern( &B, NR_PIXBLOCK_MODE_R8G8B8A8N,
148                                final_bbox.x0, final_bbox.y0, final_bbox.x1, final_bbox.y1,
149                                px, 4 * width, FALSE, FALSE );
151      unsigned char dtc[4];
152      dtc[0] = NR_RGBA32_R(bgcolor);
153      dtc[1] = NR_RGBA32_G(bgcolor);
154      dtc[2] = NR_RGBA32_B(bgcolor);
155      dtc[3] = NR_RGBA32_A(bgcolor);
157      for (unsigned int fy = 0; fy < height; fy++) {
158          guchar *p = NR_PIXBLOCK_PX(&B) + fy * B.rs;
159          for (unsigned int fx = 0; fx < width; fx++) {
160              for (int i = 0; i < 4; i++) {
161                  *p++ = dtc[i];
162              }
163          }
164      }
166      nr_arena_item_invoke_render(NULL, root, &final_bbox, &B, NR_ARENA_ITEM_RENDER_NO_CACHE );
168      GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(px, GDK_COLORSPACE_RGB,
169                                           TRUE,
170                                           8, width, height, width * 4,
171                                           (GdkPixbufDestroyNotify)g_free,
172                                           NULL);
174 //    gdk_pixbuf_save (pixbuf, "C:\\temp\\internal.jpg", "jpeg", NULL, "quality","100", NULL);
176     return pixbuf;
179 /*
180   Local Variables:
181   mode:c++
182   c-file-style:"stroustrup"
183   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
184   indent-tabs-mode:nil
185   fill-column:99
186   End:
187 */
188 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :