1 /** \file
2 * SPIcon: Generic icon widget
3 */
4 /*
5 * Authors:
6 * Lauris Kaplinski <lauris@kaplinski.com>
7 * Bryce Harrington <brycehar@bryceharrington.org>
8 * bulia byak <buliabyak@users.sf.net>
9 *
10 * Copyright (C) 2001-2005 authors
11 * Copyright (C) 2001 Ximian, Inc.
12 * Copyright (C) 2004 John Cliff
13 *
14 * Released under GNU GPL, read the file 'COPYING' for more information
15 *
16 */
18 #ifdef HAVE_CONFIG_H
19 # include "config.h"
20 #endif
22 #include <glib/gmem.h>
23 #include <gtk/gtk.h>
24 #include "sp-namedview.h"
25 #include "selection.h"
26 #include "inkscape.h"
27 #include "inkscape-stock.h"
28 #include "sp-rect.h"
29 #include "document-private.h"
30 #include "display/nr-arena.h"
31 #include "display/nr-arena-item.h"
33 #include "ui/cache/svg_preview_cache.h"
35 GdkPixbuf* render_pixbuf(NRArenaItem* root, double scale_factor, const NR::Rect& dbox, unsigned psize) {
36 NRGC gc(NULL);
37 NRMatrix t;
39 nr_matrix_set_scale(&t, scale_factor, scale_factor);
40 nr_arena_item_set_transform(root, &t);
42 nr_matrix_set_identity(&gc.transform);
43 nr_arena_item_invoke_update( root, NULL, &gc,
44 NR_ARENA_ITEM_STATE_ALL,
45 NR_ARENA_ITEM_STATE_NONE );
47 /* Item integer bbox in points */
48 NRRectL ibox;
49 ibox.x0 = (int) floor(scale_factor * dbox.min()[NR::X] + 0.5);
50 ibox.y0 = (int) floor(scale_factor * dbox.min()[NR::Y] + 0.5);
51 ibox.x1 = (int) floor(scale_factor * dbox.max()[NR::X] + 0.5);
52 ibox.y1 = (int) floor(scale_factor * dbox.max()[NR::Y] + 0.5);
54 /* Find visible area */
55 int width = ibox.x1 - ibox.x0;
56 int height = ibox.y1 - ibox.y0;
57 int dx = psize;
58 int dy = psize;
59 dx = (dx - width)/2; // watch out for size, since 'unsigned'-'signed' can cause problems if the result is negative
60 dy = (dy - height)/2;
62 NRRectL area;
63 area.x0 = ibox.x0 - dx;
64 area.y0 = ibox.y0 - dy;
65 area.x1 = area.x0 + psize;
66 area.y1 = area.y0 + psize;
68 /* Actual renderable area */
69 NRRectL ua;
70 ua.x0 = std::max(ibox.x0, area.x0);
71 ua.y0 = std::max(ibox.y0, area.y0);
72 ua.x1 = std::min(ibox.x1, area.x1);
73 ua.y1 = std::min(ibox.y1, area.y1);
75 /* Set up pixblock */
76 guchar *px = g_new(guchar, 4 * psize * psize);
77 memset(px, 0x00, 4 * psize * psize);
79 /* Render */
80 NRPixBlock B;
81 nr_pixblock_setup_extern( &B, NR_PIXBLOCK_MODE_R8G8B8A8N,
82 ua.x0, ua.y0, ua.x1, ua.y1,
83 px + 4 * psize * (ua.y0 - area.y0) +
84 4 * (ua.x0 - area.x0),
85 4 * psize, FALSE, FALSE );
86 nr_arena_item_invoke_render(NULL, root, &ua, &B,
87 NR_ARENA_ITEM_RENDER_NO_CACHE );
88 nr_pixblock_release(&B);
90 GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(px,
91 GDK_COLORSPACE_RGB,
92 TRUE,
93 8, psize, psize, psize * 4,
94 (GdkPixbufDestroyNotify)g_free,
95 NULL);
97 return pixbuf;
98 }
100 namespace Inkscape {
101 namespace UI {
102 namespace Cache {
104 SvgPreview::SvgPreview()
105 {
106 }
108 SvgPreview::~SvgPreview()
109 {
110 }
112 Glib::ustring SvgPreview::cache_key(gchar const *uri, gchar const *name, unsigned psize) const {
113 Glib::ustring key;
114 key += (uri!=NULL) ? uri : "";
115 key += ":";
116 key += (name!=NULL) ? name : "unknown";
117 key += ":";
118 key += psize;
119 return key;
120 }
122 GdkPixbuf* SvgPreview::get_preview_from_cache(const Glib::ustring& key) {
123 std::map<Glib::ustring, GdkPixbuf *>::iterator found = _pixmap_cache.find(key);
124 if ( found != _pixmap_cache.end() ) {
125 return found->second;
126 }
127 return NULL;
128 }
130 void SvgPreview::set_preview_in_cache(const Glib::ustring& key, GdkPixbuf* px) {
131 _pixmap_cache[key] = px;
132 }
134 GdkPixbuf* SvgPreview::get_preview(const gchar* uri, const gchar* id, NRArenaItem *root,
135 double scale_factor, unsigned int psize) {
136 // First try looking up the cached preview in the cache map
137 Glib::ustring key = cache_key(uri, id, psize);
138 GdkPixbuf* px = get_preview_from_cache(key);
140 if (px == NULL) {
141 /*
142 px = render_pixbuf(root, scale_factor, dbox, psize);
143 set_preview_in_cache(key, px);
144 */
145 }
146 return px;
147 }
149 };
150 };
151 };