4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2001, the ROX-Filer team.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* pixmaps.c - code for handling pixmaps */
27 /* Remove pixmaps from the cache when they haven't been accessed for
28 * this period of time (seconds).
31 #define PIXMAP_PURGE_TIME 1200
38 #include <gdk-pixbuf/gdk-pixbuf.h>
39 #include "collection.h"
45 #include "gui_support.h"
49 GFSCache
*pixmap_cache
= NULL
;
51 static const char * bad_xpm
[] = {
69 MaskedPixmap
*im_error
;
70 MaskedPixmap
*im_unknown
;
71 MaskedPixmap
*im_symlink
;
73 MaskedPixmap
*im_unmounted
;
74 MaskedPixmap
*im_mounted
;
75 MaskedPixmap
*im_multiple
;
76 MaskedPixmap
*im_exec_file
;
77 MaskedPixmap
*im_appdir
;
79 MaskedPixmap
*im_help
;
81 /* Static prototypes */
83 static void load_default_pixmaps(void);
84 static MaskedPixmap
*load(char *pathname
, gpointer data
);
85 static void ref(MaskedPixmap
*mp
, gpointer data
);
86 static void unref(MaskedPixmap
*mp
, gpointer data
);
87 static int getref(MaskedPixmap
*mp
);
88 static gint
purge(gpointer data
);
89 static MaskedPixmap
*image_from_file(char *path
);
90 static MaskedPixmap
*get_bad_image(void);
91 static MaskedPixmap
*image_from_pixbuf(GdkPixbuf
*pixbuf
);
92 static GdkPixbuf
*scale_pixbuf(GdkPixbuf
*src
, int max_w
, int max_h
);
93 static GdkPixbuf
*scale_pixbuf_up(GdkPixbuf
*src
, int max_w
, int max_h
);
96 /****************************************************************
97 * EXTERNAL INTERFACE *
98 ****************************************************************/
100 void pixmaps_init(void)
104 gtk_widget_push_visual(gdk_rgb_get_visual());
106 gtk_widget_push_colormap(gdk_rgb_get_cmap());
108 pixmap_cache
= g_fscache_new((GFSLoadFunc
) load
,
111 (GFSGetRefFunc
) getref
,
112 NULL
, /* Update func */
115 gtk_timeout_add(10000, purge
, NULL
);
117 load_default_pixmaps();
120 /* 'name' is relative to app_dir. Always returns with a valid image. */
121 MaskedPixmap
*load_pixmap(char *name
)
123 MaskedPixmap
*retval
;
125 retval
= image_from_file(make_path(app_dir
, name
)->str
);
127 retval
= get_bad_image();
131 /* Load all the standard pixmaps */
132 static void load_default_pixmaps(void)
134 im_error
= load_pixmap("pixmaps/error.xpm");
135 im_unknown
= load_pixmap("pixmaps/unknown.xpm");
136 im_symlink
= load_pixmap("pixmaps/symlink.xpm");
138 im_unmounted
= load_pixmap("pixmaps/mount.xpm");
139 im_mounted
= load_pixmap("pixmaps/mounted.xpm");
140 im_multiple
= load_pixmap("pixmaps/multiple.xpm");
141 im_exec_file
= load_pixmap("pixmaps/exec.xpm");
142 im_appdir
= load_pixmap("pixmaps/application.xpm");
144 im_help
= load_pixmap("pixmaps/help.xpm");
147 void pixmap_ref(MaskedPixmap
*mp
)
152 void pixmap_unref(MaskedPixmap
*mp
)
157 void pixmap_make_huge(MaskedPixmap
*mp
)
164 g_return_if_fail(mp
->huge_pixbuf
!= NULL
);
166 hg
= scale_pixbuf_up(mp
->huge_pixbuf
,
172 gdk_pixbuf_render_pixmap_and_mask(hg
,
176 mp
->huge_width
= gdk_pixbuf_get_width(hg
);
177 mp
->huge_height
= gdk_pixbuf_get_height(hg
);
178 gdk_pixbuf_unref(hg
);
181 if (!mp
->huge_pixmap
)
183 gdk_pixmap_ref(mp
->pixmap
);
185 gdk_bitmap_ref(mp
->mask
);
186 mp
->huge_pixmap
= mp
->pixmap
;
187 mp
->huge_mask
= mp
->mask
;
188 mp
->huge_width
= mp
->width
;
189 mp
->huge_height
= mp
->height
;
193 void pixmap_make_small(MaskedPixmap
*mp
)
200 g_return_if_fail(mp
->huge_pixbuf
!= NULL
);
202 sm
= scale_pixbuf(mp
->huge_pixbuf
, SMALL_WIDTH
, SMALL_HEIGHT
);
206 gdk_pixbuf_render_pixmap_and_mask(sm
,
210 mp
->sm_width
= gdk_pixbuf_get_width(sm
);
211 mp
->sm_height
= gdk_pixbuf_get_height(sm
);
212 gdk_pixbuf_unref(sm
);
218 gdk_pixmap_ref(mp
->pixmap
);
220 gdk_bitmap_ref(mp
->mask
);
221 mp
->sm_pixmap
= mp
->pixmap
;
222 mp
->sm_mask
= mp
->mask
;
223 mp
->sm_width
= mp
->width
;
224 mp
->sm_height
= mp
->height
;
227 /****************************************************************
228 * INTERNAL FUNCTIONS *
229 ****************************************************************/
231 /* Load the image 'path' and return a pointer to the resulting
232 * MaskedPixmap. NULL on failure.
234 static MaskedPixmap
*image_from_file(char *path
)
239 pixbuf
= gdk_pixbuf_new_from_file(path
241 , NULL
/* XXX: Maybe something should go here? */
247 image
= image_from_pixbuf(pixbuf
);
248 gdk_pixbuf_unref(pixbuf
);
253 /* Scale src down to fit in max_w, max_h and return the new pixbuf.
254 * If src is small enough, then ref it and return that.
256 static GdkPixbuf
*scale_pixbuf(GdkPixbuf
*src
, int max_w
, int max_h
)
260 w
= gdk_pixbuf_get_width(src
);
261 h
= gdk_pixbuf_get_height(src
);
263 if (w
<= max_w
&& h
<= max_h
)
270 float scale_x
= ((float) w
) / max_w
;
271 float scale_y
= ((float) h
) / max_h
;
272 float scale
= MAX(scale_x
, scale_y
);
274 return gdk_pixbuf_scale_simple(src
,
277 GDK_INTERP_BILINEAR
);
281 /* Scale src up to fit in max_w, max_h and return the new pixbuf.
282 * If src is that size or bigger, then ref it and return that.
284 static GdkPixbuf
*scale_pixbuf_up(GdkPixbuf
*src
, int max_w
, int max_h
)
288 w
= gdk_pixbuf_get_width(src
);
289 h
= gdk_pixbuf_get_height(src
);
291 if (w
== 0 || h
== 0 || (w
>= max_w
&& h
>= max_h
))
298 float scale_x
= max_w
/ ((float) w
);
299 float scale_y
= max_h
/ ((float) h
);
300 float scale
= MIN(scale_x
, scale_y
);
302 return gdk_pixbuf_scale_simple(src
,
305 GDK_INTERP_BILINEAR
);
309 /* Turn a full-size pixbuf into a MaskedPixmap */
310 static MaskedPixmap
*image_from_pixbuf(GdkPixbuf
*full_size
)
313 GdkPixbuf
*huge_pixbuf
, *normal_pixbuf
;
317 g_return_val_if_fail(full_size
!= NULL
, NULL
);
319 huge_pixbuf
= scale_pixbuf(full_size
, HUGE_WIDTH
, HUGE_HEIGHT
);
320 g_return_val_if_fail(huge_pixbuf
!= NULL
, NULL
);
322 normal_pixbuf
= scale_pixbuf(huge_pixbuf
, ICON_WIDTH
, ICON_HEIGHT
);
323 g_return_val_if_fail(normal_pixbuf
!= NULL
, NULL
);
325 gdk_pixbuf_render_pixmap_and_mask(normal_pixbuf
, &pixmap
, &mask
, 128);
329 gdk_pixbuf_unref(huge_pixbuf
);
330 gdk_pixbuf_unref(normal_pixbuf
);
334 mp
= g_new(MaskedPixmap
, 1);
335 mp
->huge_pixbuf
= huge_pixbuf
;
340 mp
->width
= gdk_pixbuf_get_width(normal_pixbuf
);
341 mp
->height
= gdk_pixbuf_get_height(normal_pixbuf
);
343 gdk_pixbuf_unref(normal_pixbuf
);
345 mp
->huge_pixmap
= NULL
;
346 mp
->huge_mask
= NULL
;
348 mp
->huge_height
= -1;
350 mp
->sm_pixmap
= NULL
;
358 /* Return a pointer to the (static) bad image. The ref counter will ensure
359 * that the image is never freed.
361 static MaskedPixmap
*get_bad_image(void)
366 bad
= gdk_pixbuf_new_from_xpm_data(bad_xpm
);
367 mp
= image_from_pixbuf(bad
);
368 gdk_pixbuf_unref(bad
);
373 static MaskedPixmap
*load(char *pathname
, gpointer user_data
)
375 return image_from_file(pathname
);
378 static void ref(MaskedPixmap
*mp
, gpointer data
)
380 /* printf("[ ref %p %d->%d ]\n", mp, mp->ref, mp->ref + 1); */
386 static void unref(MaskedPixmap
*mp
, gpointer data
)
388 /* printf("[ unref %p %d->%d ]\n", mp, mp->ref, mp->ref - 1); */
390 if (mp
&& --mp
->ref
== 0)
394 gdk_pixbuf_unref(mp
->huge_pixbuf
);
398 gdk_pixmap_unref(mp
->huge_pixmap
);
400 gdk_bitmap_unref(mp
->huge_mask
);
403 gdk_pixmap_unref(mp
->pixmap
);
405 gdk_bitmap_unref(mp
->mask
);
408 gdk_pixmap_unref(mp
->sm_pixmap
);
410 gdk_bitmap_unref(mp
->sm_mask
);
416 static int getref(MaskedPixmap
*mp
)
418 return mp
? mp
->ref
: 0;
421 /* Called now and then to clear out old pixmaps */
422 static gint
purge(gpointer data
)
424 g_fscache_purge(pixmap_cache
, PIXMAP_PURGE_TIME
);