Code

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