4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2000, Thomas Leonard, <tal197@users.sourceforge.net>.
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 */
25 * 2000/04/11 Imlib support added
26 * Christiansen Merel <c.merel@wanadoo.fr>
32 /* Remove pixmaps from the cache when they haven't been accessed for
33 * this period of time (seconds).
36 #define PIXMAP_PURGE_TIME 1200
43 #include <gdk/gdkprivate.h> /* XXX - find another way to do this */
44 #include "collection.h"
46 # include <gdk_imlib.h>
53 #include "gui_support.h"
57 GFSCache
*pixmap_cache
= NULL
;
59 static char * bad_xpm
[] = {
77 MaskedPixmap
*im_error
;
78 MaskedPixmap
*im_unknown
;
79 MaskedPixmap
*im_symlink
;
81 MaskedPixmap
*im_unmounted
;
82 MaskedPixmap
*im_mounted
;
83 MaskedPixmap
*im_multiple
;
84 MaskedPixmap
*im_exec_file
;
85 MaskedPixmap
*im_appdir
;
87 MaskedPixmap
*im_up_icon
;
88 MaskedPixmap
*im_home_icon
;
89 MaskedPixmap
*im_refresh_icon
;
90 MaskedPixmap
*im_help
;
92 /* Static prototypes */
94 static MaskedPixmap
*load_pixmap(char *name
);
95 static void load_default_pixmaps(void);
96 static MaskedPixmap
*load(char *pathname
, gpointer data
);
97 static void ref(MaskedPixmap
*mp
, gpointer data
);
98 static void unref(MaskedPixmap
*mp
, gpointer data
);
99 static int getref(MaskedPixmap
*mp
);
100 static gint
purge(gpointer data
);
101 static MaskedPixmap
*image_from_file(char *path
);
102 static MaskedPixmap
*get_bad_image(void);
104 static GdkImlibImage
*make_half_size(GdkImlibImage
*big
);
108 /****************************************************************
109 * EXTERNAL INTERFACE *
110 ****************************************************************/
112 void pixmaps_init(void)
117 gtk_widget_push_visual(gdk_imlib_get_visual());
118 gtk_widget_push_colormap(gdk_imlib_get_colormap());
121 pixmap_cache
= g_fscache_new((GFSLoadFunc
) load
,
124 (GFSGetRefFunc
) getref
,
125 NULL
, /* Update func */
128 gtk_timeout_add(10000, purge
, NULL
);
130 load_default_pixmaps();
133 /* 'name' is relative to app_dir. Always returns with a valid image. */
134 MaskedPixmap
*load_pixmap(char *name
)
136 MaskedPixmap
*retval
;
138 retval
= image_from_file(make_path(app_dir
, name
)->str
);
140 retval
= get_bad_image();
144 /* Load all the standard pixmaps */
145 static void load_default_pixmaps(void)
147 im_error
= load_pixmap("pixmaps/error.xpm");
148 im_unknown
= load_pixmap("pixmaps/unknown.xpm");
149 im_symlink
= load_pixmap("pixmaps/symlink.xpm");
151 im_unmounted
= load_pixmap("pixmaps/mount.xpm");
152 im_mounted
= load_pixmap("pixmaps/mounted.xpm");
153 im_multiple
= load_pixmap("pixmaps/multiple.xpm");
154 im_exec_file
= load_pixmap("pixmaps/exec.xpm");
155 im_appdir
= load_pixmap("pixmaps/application.xpm");
157 im_up_icon
= load_pixmap("pixmaps/up.xpm");
158 im_home_icon
= load_pixmap("pixmaps/home.xpm");
159 im_refresh_icon
= load_pixmap("pixmaps/refresh.xpm");
160 im_help
= load_pixmap("pixmaps/help.xpm");
163 void pixmap_ref(MaskedPixmap
*mp
)
165 ref(mp
, pixmap_cache
->user_data
);
168 void pixmap_unref(MaskedPixmap
*mp
)
170 unref(mp
, pixmap_cache
->user_data
);
173 void pixmap_make_small(MaskedPixmap
*mp
)
181 GdkImlibImage
*small
;
183 small
= make_half_size(mp
->image
);
185 if (small
&& gdk_imlib_render(small
,
186 small
->rgb_width
, small
->rgb_height
))
188 mp
->sm_pixmap
= gdk_imlib_move_image(small
);
189 mp
->sm_mask
= gdk_imlib_move_mask(small
);
190 mp
->sm_width
= small
->width
;
191 mp
->sm_height
= small
->height
;
195 gdk_imlib_kill_image(small
);
200 gdk_pixmap_ref(mp
->pixmap
);
202 gdk_bitmap_ref(mp
->mask
);
203 mp
->sm_pixmap
= mp
->pixmap
;
204 mp
->sm_mask
= mp
->mask
;
205 mp
->sm_width
= mp
->width
;
206 mp
->sm_height
= mp
->height
;
209 /****************************************************************
210 * INTERNAL FUNCTIONS *
211 ****************************************************************/
213 /* Load the image 'path' and return a pointer to the resulting
214 * MaskedPixmap. NULL on failure.
216 static MaskedPixmap
*image_from_file(char *path
)
224 GdkImlibImage
*image
;
226 image
= gdk_imlib_load_image(path
);
230 /* Avoid ImLib cache - ours is better! */
231 gdk_imlib_changed_image(image
);
233 if (!gdk_imlib_render(image
, image
->rgb_width
, image
->rgb_height
))
235 gdk_imlib_kill_image(image
);
239 pixmap
= image
->pixmap
;
240 mask
= image
->shape_mask
;
241 width
= image
->width
;
242 height
= image
->height
;
244 pixmap
= gdk_pixmap_colormap_create_from_xpm(NULL
,
245 gtk_widget_get_default_colormap(),
252 width
= ((GdkPixmapPrivate
*) pixmap
)->width
;
253 height
= ((GdkPixmapPrivate
*) pixmap
)->height
;
256 mp
= g_new(MaskedPixmap
, 1);
265 mp
->sm_pixmap
= NULL
;
271 /* Return a pointer to the (static) bad image. The ref counter will ensure
272 * that the image is never freed.
274 static MaskedPixmap
*get_bad_image(void)
276 static MaskedPixmap
*image
= NULL
;
280 image
= g_new(MaskedPixmap
, 1);
283 image
->pixmap
= gdk_pixmap_colormap_create_from_xpm_d(NULL
,
284 gtk_widget_get_default_colormap(),
285 &image
->mask
, NULL
, bad_xpm
);
290 image
->sm_pixmap
= NULL
;
291 image
->sm_mask
= NULL
;
295 image
->width
= ((GdkPixmapPrivate
*) image
->pixmap
)->width
;
296 image
->height
= ((GdkPixmapPrivate
*) image
->pixmap
)->height
;
301 static MaskedPixmap
*load(char *pathname
, gpointer user_data
)
303 return image_from_file(pathname
);
306 static void ref(MaskedPixmap
*mp
, gpointer data
)
308 /* printf("[ ref %p %d->%d ]\n", mp, mp->ref, mp->ref + 1); */
314 static void unref(MaskedPixmap
*mp
, gpointer data
)
316 /* printf("[ unref %p %d->%d ]\n", mp, mp->ref, mp->ref - 1); */
318 if (mp
&& --mp
->ref
== 0)
323 gdk_imlib_kill_image(mp
->image
);
328 gdk_pixmap_unref(mp
->pixmap
);
330 gdk_bitmap_unref(mp
->mask
);
333 gdk_pixmap_unref(mp
->sm_pixmap
);
335 gdk_bitmap_unref(mp
->sm_mask
);
340 static int getref(MaskedPixmap
*mp
)
345 /* Called now and then to clear out old pixmaps */
346 static gint
purge(gpointer data
)
348 g_fscache_purge(pixmap_cache
, PIXMAP_PURGE_TIME
);
355 /* Returns data to make an 1/4 size image of 'big'. g_free() the result. */
356 static GdkImlibImage
*make_half_size(GdkImlibImage
*big
)
358 int line_size
= big
->width
* 3;
359 int sw
= big
->width
>> 1;
360 int sh
= big
->height
>> 1;
361 GdkImlibColor tr
; /* Mask colour */
362 unsigned char *small_data
, *in
, *out
;
363 GdkImlibImage
*small
;
365 GtkStyle
*style
= gtk_widget_get_default_style();
366 GdkColor
*bg
= &style
->bg
[GTK_STATE_INSENSITIVE
];
368 gdk_imlib_get_image_shape(big
, &tr
);
369 small_data
= g_malloc(sw
* sh
* 3);
373 for (y
= 0; y
< sh
; y
++)
375 in
= big
->rgb_data
+ y
* line_size
* 2;
377 for (x
= 0; x
< sw
; x
++)
379 int r1
= in
[0], r2
= in
[3];
380 int r3
= in
[0 + line_size
], r4
= in
[3 + line_size
];
381 int g1
= in
[1], g2
= in
[4];
382 int g3
= in
[1 + line_size
], g4
= in
[4 + line_size
];
383 int b1
= in
[2], b2
= in
[5];
384 int b3
= in
[2 + line_size
], b4
= in
[5 + line_size
];
385 int m
= 0; /* No. trans pixels */
387 if (r1
== tr
.r
&& g1
== tr
.g
&& b1
== tr
.b
)
394 if (r2
== tr
.r
&& g2
== tr
.g
&& b2
== tr
.b
)
401 if (r3
== tr
.r
&& g3
== tr
.g
&& b3
== tr
.b
)
408 if (r4
== tr
.r
&& g4
== tr
.g
&& b4
== tr
.b
)
418 out
[0] = (r1
+ r2
+ r3
+ r4
) >> 2;
419 out
[1] = (g1
+ g2
+ g3
+ g4
) >> 2;
420 out
[2] = (b1
+ b2
+ b3
+ b4
) >> 2;
434 small
= gdk_imlib_create_image_from_data(small_data
, NULL
, sw
, sh
);
438 gdk_imlib_set_image_shape(small
, &tr
);