Code

A proper fix for dock item mising icon problem. Fixes bug #658055.
[inkscape.git] / src / ui / cache / svg_preview_cache.cpp
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 "sp-rect.h"
28 #include "document-private.h"
29 #include "display/nr-arena.h"
30 #include "display/nr-arena-item.h"
32 #include "ui/cache/svg_preview_cache.h"
34 GdkPixbuf* render_pixbuf(NRArenaItem* root, double scale_factor, const Geom::Rect& dbox, unsigned psize) {
35     NRGC gc(NULL);
37     Geom::Matrix t(Geom::Scale(scale_factor, scale_factor));
38     nr_arena_item_set_transform(root, t);
40     gc.transform.setIdentity();
41     nr_arena_item_invoke_update( root, NULL, &gc,
42                                  NR_ARENA_ITEM_STATE_ALL,
43                                  NR_ARENA_ITEM_STATE_NONE );
45     /* Item integer bbox in points */
46     NRRectL ibox;
47     ibox.x0 = (int) floor(scale_factor * dbox.min()[Geom::X] + 0.5);
48     ibox.y0 = (int) floor(scale_factor * dbox.min()[Geom::Y] + 0.5);
49     ibox.x1 = (int) floor(scale_factor * dbox.max()[Geom::X] + 0.5);
50     ibox.y1 = (int) floor(scale_factor * dbox.max()[Geom::Y] + 0.5);
52     /* Find visible area */
53     int width = ibox.x1 - ibox.x0;
54     int height = ibox.y1 - ibox.y0;
55     int dx = psize;
56     int dy = psize;
57     dx = (dx - width)/2; // watch out for size, since 'unsigned'-'signed' can cause problems if the result is negative
58     dy = (dy - height)/2;
60     NRRectL area;
61     area.x0 = ibox.x0 - dx;
62     area.y0 = ibox.y0 - dy;
63     area.x1 = area.x0 + psize;
64     area.y1 = area.y0 + psize;
66     /* Actual renderable area */
67     NRRectL ua;
68     ua.x0 = std::max(ibox.x0, area.x0);
69     ua.y0 = std::max(ibox.y0, area.y0);
70     ua.x1 = std::min(ibox.x1, area.x1);
71     ua.y1 = std::min(ibox.y1, area.y1);
73     /* Set up pixblock */
74     guchar *px = g_new(guchar, 4 * psize * psize);
75     memset(px, 0x00, 4 * psize * psize);
77     /* Render */
78     NRPixBlock B;
79     nr_pixblock_setup_extern( &B, NR_PIXBLOCK_MODE_R8G8B8A8N,
80                               ua.x0, ua.y0, ua.x1, ua.y1,
81                               px + 4 * psize * (ua.y0 - area.y0) +
82                               4 * (ua.x0 - area.x0),
83                               4 * psize, FALSE, FALSE );
84     nr_arena_item_invoke_render(NULL, root, &ua, &B,
85                                  NR_ARENA_ITEM_RENDER_NO_CACHE );
86     nr_pixblock_release(&B);
88     GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(px,
89                                       GDK_COLORSPACE_RGB,
90                                       TRUE,
91                                       8, psize, psize, psize * 4,
92                                       (GdkPixbufDestroyNotify)g_free,
93                                       NULL);
95     return pixbuf;
96 }
98 namespace Inkscape {
99 namespace UI {
100 namespace Cache {
102 SvgPreview::SvgPreview()
106 SvgPreview::~SvgPreview()
110 Glib::ustring SvgPreview::cache_key(gchar const *uri, gchar const *name, unsigned psize) const {
111     Glib::ustring key;
112     key += (uri!=NULL)  ? uri  : "";
113     key += ":";
114     key += (name!=NULL) ? name : "unknown";
115     key += ":";
116     key += psize;
117     return key;
120 GdkPixbuf* SvgPreview::get_preview_from_cache(const Glib::ustring& key) {
121     std::map<Glib::ustring, GdkPixbuf *>::iterator found = _pixmap_cache.find(key);
122     if ( found != _pixmap_cache.end() ) {
123         return found->second;
124     }
125     return NULL;
128 void SvgPreview::set_preview_in_cache(const Glib::ustring& key, GdkPixbuf* px) {
129     _pixmap_cache[key] = px;
132 GdkPixbuf* SvgPreview::get_preview(const gchar* uri, const gchar* id, NRArenaItem */*root*/,
133                                    double /*scale_factor*/, unsigned int psize) {
134     // First try looking up the cached preview in the cache map
135     Glib::ustring key = cache_key(uri, id, psize);
136     GdkPixbuf* px = get_preview_from_cache(key);
138     if (px == NULL) {
139         /*
140             px = render_pixbuf(root, scale_factor, dbox, psize);
141             set_preview_in_cache(key, px);
142         */
143     }
144     return px;
147 };
148 };
149 };