mirror of
https://gitlab.gnome.org/GNOME/nautilus
synced 2024-08-25 02:36:07 +00:00
fixed bug 1408, where thumbnail frames had the wrong shadow. Fixed by
fixed bug 1408, where thumbnail frames had the wrong shadow. Fixed by maintaining two versions of the thumbnail, for the aa and non-aa cases. Also, create the frame from an image instead of drawing commands.
This commit is contained in:
parent
46d9cf6a56
commit
99a82ffb40
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
|||
2000-07-30 Andy Hertzfeld <andy@eazel.com>
|
||||
|
||||
fixed bug 1408, thumbnails do not have the right shadow. Fixed by maintaining
|
||||
different thumbnails for the anti-aliased and non-anti-aliased cases.
|
||||
|
||||
* libnautilus-extensions/nautilus-graphic-effects.c,h:
|
||||
(stretch_frame_image), (nautilus_embed_image_in_frame):
|
||||
got rid of old draw_frame routine, and added nautilus_embed_image_in_frame
|
||||
* libnautilus-extensions/nautilus-icon-factory.c:
|
||||
(nautilus_icon_factory_get_icon_for_file), (make_thumbnail_path),
|
||||
(nautilus_icon_factory_get_thumbnail_uri), (check_for_thumbnails),
|
||||
(load_thumbnail_frame), (nautilus_icon_factory_make_thumbnails):
|
||||
called nautilus_embed_image_in_frame to make the thumbnail frame;
|
||||
also, added the aa flag to various routines and respected it, using
|
||||
a different name and frame for the anti-aliased versions.
|
||||
|
||||
* icons/Makefile.am:
|
||||
* icons/thumbnail_frame.png:
|
||||
* icons/thumbnail_frame.aa.png:
|
||||
added frame images to use for both cases (anti-aliased and non-aa)
|
||||
|
||||
2000-07-30 Mathieu Lacage <mathieu@eazel.com>
|
||||
|
||||
Make nautilus build with the latest oaf changes.
|
||||
|
|
|
@ -164,6 +164,8 @@ icon_DATA =\
|
|||
tabright.png \
|
||||
temp-home.png \
|
||||
themes.png \
|
||||
thumbnail_frame.aa.png \
|
||||
thumbnail_frame.png \
|
||||
trash-empty.png \
|
||||
trash-full.png \
|
||||
uparrow.png \
|
||||
|
|
BIN
icons/thumbnail_frame.aa.png
Normal file
BIN
icons/thumbnail_frame.aa.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 907 B |
BIN
icons/thumbnail_frame.png
Normal file
BIN
icons/thumbnail_frame.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 546 B |
|
@ -26,6 +26,11 @@
|
|||
and selection hilighting */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <libart_lgpl/art_config.h>
|
||||
#include <libart_lgpl/art_rect.h>
|
||||
#include <libart_lgpl/art_rgb.h>
|
||||
|
||||
#include "nautilus-graphic-effects.h"
|
||||
|
||||
/* shared utility to create a new pixbuf from the passed-in one */
|
||||
|
@ -221,92 +226,39 @@ nautilus_create_colorized_pixbuf (GdkPixbuf *src,
|
|||
return dest;
|
||||
}
|
||||
|
||||
/* draw a frame with a drop shadow into the passed in pixbuf */
|
||||
/* utility to stretch a frame to the desired size */
|
||||
/* FIXME: right now it justs does a simple scale - it should do it by replicating the "stretchable" area instead of
|
||||
scaling everything uniformly */
|
||||
|
||||
void
|
||||
nautilus_draw_frame (GdkPixbuf *frame_pixbuf)
|
||||
static GdkPixbuf *
|
||||
stretch_frame_image (GdkPixbuf *frame_image, int left_offset, int top_offset, int right_offset, int bottom_offset, int dest_width, int dest_height)
|
||||
{
|
||||
int index, h_index, last_index, pin_width;
|
||||
int width, height, depth, rowstride, fill_value;
|
||||
guchar *pixels, *temp_pixels;
|
||||
return gdk_pixbuf_scale_simple (frame_image, dest_width, dest_height, GDK_INTERP_BILINEAR);
|
||||
}
|
||||
|
||||
|
||||
/* utility to draw the middle section of the frame in a loop */
|
||||
|
||||
/* draw an arbitrary frame around an image, with the result passed back in a newly allocated pixbuf */
|
||||
GdkPixbuf *
|
||||
nautilus_embed_image_in_frame (GdkPixbuf *source_image, GdkPixbuf *frame_image, int left_offset, int top_offset, int right_offset, int bottom_offset)
|
||||
{
|
||||
GdkPixbuf *result_pixbuf;
|
||||
int source_width, source_height;
|
||||
int dest_width, dest_height;
|
||||
|
||||
width = gdk_pixbuf_get_width (frame_pixbuf);
|
||||
height = gdk_pixbuf_get_height (frame_pixbuf);
|
||||
depth = gdk_pixbuf_get_bits_per_sample (frame_pixbuf);
|
||||
pixels = gdk_pixbuf_get_pixels (frame_pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (frame_pixbuf);
|
||||
source_width = gdk_pixbuf_get_width (source_image);
|
||||
source_height = gdk_pixbuf_get_height (source_image);
|
||||
|
||||
/* loop through the pixbuf a scaleline at a time, drawing the frame */
|
||||
for (index = 0; index < height; index++) {
|
||||
/* special case the first and last few lines to make them dark */
|
||||
fill_value = 239;
|
||||
pin_width = width;
|
||||
last_index = height - index;
|
||||
if (index == 0)
|
||||
fill_value = 0;
|
||||
else if (index > (height - 6)) {
|
||||
fill_value = 107 + (index - (height - 5)) * 37;
|
||||
pin_width = width - (height - index);
|
||||
}
|
||||
/* memset(pixels, fill_value, rowstride); */
|
||||
temp_pixels = pixels;
|
||||
for (h_index = 0; h_index < pin_width; h_index++) {
|
||||
*temp_pixels++ = fill_value;
|
||||
*temp_pixels++ = fill_value;
|
||||
*temp_pixels++ = fill_value;
|
||||
*temp_pixels++ = ((last_index < 6) && ((4 - last_index) > h_index)) ? 0 : 255;
|
||||
}
|
||||
dest_width = source_width + left_offset + right_offset;
|
||||
dest_height = source_height + top_offset + bottom_offset;
|
||||
|
||||
result_pixbuf = stretch_frame_image (frame_image, left_offset, top_offset, right_offset, bottom_offset, dest_width, dest_height);
|
||||
|
||||
/* draw the frame at the edge for each scanline */
|
||||
if (last_index > 5) {
|
||||
temp_pixels = pixels;
|
||||
*temp_pixels++ = 0;
|
||||
*temp_pixels++ = 0;
|
||||
*temp_pixels++ = 0;
|
||||
*temp_pixels++ = 255;
|
||||
}
|
||||
|
||||
pixels += rowstride;
|
||||
|
||||
/* handle the last 5 pixels specially for the drop shadow */
|
||||
|
||||
temp_pixels = pixels - 5*4;
|
||||
/* Finally, copy the source image into the framed area */
|
||||
gdk_pixbuf_copy_area (source_image, 0, 0, source_width, source_height, result_pixbuf, left_offset, top_offset);
|
||||
|
||||
if (last_index > 4) {
|
||||
*temp_pixels++ = 107;
|
||||
*temp_pixels++ = 107;
|
||||
*temp_pixels++ = 107;
|
||||
*temp_pixels++ = 255;
|
||||
} else temp_pixels += 4;
|
||||
|
||||
if (last_index > 3) {
|
||||
*temp_pixels++ = 144;
|
||||
*temp_pixels++ = 144;
|
||||
*temp_pixels++ = 144;
|
||||
*temp_pixels++ = index < 1 ? 0 : 255;
|
||||
} else temp_pixels += 4;
|
||||
|
||||
if (last_index > 2) {
|
||||
*temp_pixels++ = 181;
|
||||
*temp_pixels++ = 181;
|
||||
*temp_pixels++ = 181;
|
||||
*temp_pixels++ = index < 2 ? 0 : 255;
|
||||
} else temp_pixels += 4;
|
||||
|
||||
if (last_index > 1) {
|
||||
*temp_pixels++ = 218;
|
||||
*temp_pixels++ = 218;
|
||||
*temp_pixels++ = 218;
|
||||
*temp_pixels++ = index < 3 ? 0 : 255;
|
||||
} else temp_pixels += 4;
|
||||
|
||||
if (last_index > 0) {
|
||||
*temp_pixels++ = 244;
|
||||
*temp_pixels++ = 244;
|
||||
*temp_pixels++ = 244;
|
||||
*temp_pixels++ = index < 4 ? 0 : 255;
|
||||
}
|
||||
}
|
||||
return result_pixbuf;
|
||||
}
|
||||
|
||||
|
||||
|
@ -371,3 +323,4 @@ nautilus_make_semi_transparent (GdkPixbuf *src)
|
|||
|
||||
return dest_pixbuf;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,8 +41,8 @@ GdkPixbuf* nautilus_create_colorized_pixbuf (GdkPixbuf *source_pixbuf,
|
|||
int green_value,
|
||||
int blue_value);
|
||||
|
||||
/* draw a frame with a drop shadow into the passed-in pixbuf */
|
||||
void nautilus_draw_frame (GdkPixbuf *frame_pixbuf);
|
||||
/* embed in image in a frame */
|
||||
GdkPixbuf *nautilus_embed_image_in_frame (GdkPixbuf *source_image, GdkPixbuf *frame_image, int left_offset, int top_offset, int right_offset, int bottom_offset);
|
||||
|
||||
/* return a semi-transparent pixbuf from the source pixbuf using a checkboard
|
||||
stipple in the alpha channel (so it can be converted to an alpha-less pixmap) */
|
||||
|
|
|
@ -211,7 +211,8 @@ static GtkType nautilus_icon_factory_get_type (void);
|
|||
static void nautilus_icon_factory_initialize_class (NautilusIconFactoryClass *class);
|
||||
static void nautilus_icon_factory_initialize (NautilusIconFactory *factory);
|
||||
static NautilusIconFactory * nautilus_get_current_icon_factory (void);
|
||||
static char * nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file);
|
||||
static char * nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file,
|
||||
gboolean anti_aliased);
|
||||
static NautilusIconFactory * nautilus_icon_factory_new (const char *theme_name);
|
||||
static void nautilus_icon_factory_set_theme (const char *theme_name);
|
||||
static guint nautilus_scalable_icon_hash (gconstpointer p);
|
||||
|
@ -951,7 +952,7 @@ nautilus_icon_factory_get_icon_for_file (NautilusFile *file, const char* modifie
|
|||
if (nautilus_file_get_size (file) < SELF_THUMBNAIL_SIZE_THRESHOLD) {
|
||||
uri = nautilus_file_get_uri (file);
|
||||
} else if (strstr(file_uri, "/.thumbnails/") == NULL) {
|
||||
uri = nautilus_icon_factory_get_thumbnail_uri (file);
|
||||
uri = nautilus_icon_factory_get_thumbnail_uri (file, anti_aliased);
|
||||
}
|
||||
}
|
||||
g_free (mime_type);
|
||||
|
@ -1124,11 +1125,13 @@ nautilus_make_directory_and_parents (GnomeVFSURI *uri, guint permissions)
|
|||
/* utility routine that, given the uri of an image, constructs the uri to the corresponding thumbnail */
|
||||
|
||||
static char *
|
||||
make_thumbnail_path (const char *image_uri, gboolean directory_only, gboolean use_local_directory)
|
||||
make_thumbnail_path (const char *image_uri, gboolean directory_only, gboolean use_local_directory, gboolean anti_aliased)
|
||||
{
|
||||
char *thumbnail_uri, *thumbnail_path;
|
||||
char *directory_name = g_strdup (image_uri);
|
||||
char *last_slash = strrchr (directory_name, '/');
|
||||
char *dot_pos;
|
||||
|
||||
*last_slash = '\0';
|
||||
|
||||
/* either use the local directory or one in the user's home directory, as selected by the passed in flag */
|
||||
|
@ -1156,13 +1159,26 @@ make_thumbnail_path (const char *image_uri, gboolean directory_only, gboolean us
|
|||
char* old_uri = thumbnail_uri;
|
||||
thumbnail_uri = g_strdup_printf ("%s/%s", thumbnail_uri, last_slash + 1);
|
||||
g_free(old_uri);
|
||||
}
|
||||
|
||||
/* append an image suffix if the correct one isn't already present */
|
||||
if (!nautilus_istr_has_suffix (image_uri, ".png") && !directory_only) {
|
||||
char* old_uri = thumbnail_uri;
|
||||
thumbnail_uri = g_strdup_printf ("%s.png", thumbnail_uri);
|
||||
g_free(old_uri);
|
||||
/* append the anti-aliased suffix if necessary */
|
||||
if (anti_aliased) {
|
||||
char *old_uri = thumbnail_uri;
|
||||
dot_pos = strrchr (thumbnail_uri, '.');
|
||||
if (dot_pos) {
|
||||
*dot_pos = '\0';
|
||||
thumbnail_uri = g_strdup_printf ("%s.aa.%s", old_uri, dot_pos + 1);
|
||||
} else {
|
||||
thumbnail_uri = g_strconcat (old_uri, ".aa", NULL);
|
||||
}
|
||||
g_free (old_uri);
|
||||
}
|
||||
|
||||
/* append an image suffix if the correct one isn't already present */
|
||||
if (!nautilus_istr_has_suffix (image_uri, ".png")) {
|
||||
char* old_uri = thumbnail_uri;
|
||||
thumbnail_uri = g_strdup_printf ("%s.png", thumbnail_uri);
|
||||
g_free(old_uri);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (directory_name);
|
||||
|
@ -1210,6 +1226,7 @@ first_file_more_recent(const char* file_uri, const char* other_file_uri)
|
|||
typedef struct {
|
||||
char *thumbnail_uri;
|
||||
gboolean is_local;
|
||||
gboolean anti_aliased;
|
||||
} NautilusThumbnailInfo;
|
||||
|
||||
/* GCompareFunc-style function for comparing NautilusThumbnailInfos.
|
||||
|
@ -1234,7 +1251,7 @@ compare_thumbnail_info (gconstpointer a, gconstpointer b)
|
|||
*/
|
||||
|
||||
static char *
|
||||
nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file)
|
||||
nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file, gboolean anti_aliased)
|
||||
{
|
||||
NautilusIconFactory *factory;
|
||||
GnomeVFSResult result;
|
||||
|
@ -1246,7 +1263,7 @@ nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file)
|
|||
file_uri = nautilus_file_get_uri (file);
|
||||
|
||||
/* compose the uri for the thumbnail locally */
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, FALSE, TRUE);
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, FALSE, TRUE, anti_aliased);
|
||||
|
||||
/* if the thumbnail file already exists locally, simply return the uri */
|
||||
if (vfs_file_exists (thumbnail_uri)) {
|
||||
|
@ -1267,7 +1284,7 @@ nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file)
|
|||
/* now try it globally */
|
||||
if (!remake_thumbnail) {
|
||||
g_free (thumbnail_uri);
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, FALSE, FALSE);
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, FALSE, FALSE, anti_aliased);
|
||||
|
||||
/* if the thumbnail file already exists in the common area, return that uri */
|
||||
if (vfs_file_exists (thumbnail_uri)) {
|
||||
|
@ -1289,14 +1306,14 @@ nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file)
|
|||
/* make the thumbnail directory if necessary, at first try it locally */
|
||||
g_free (thumbnail_uri);
|
||||
local_flag = TRUE;
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, TRUE, local_flag);
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, TRUE, local_flag, anti_aliased);
|
||||
result = gnome_vfs_make_directory (thumbnail_uri, THUMBNAIL_DIR_PERMISSIONS);
|
||||
|
||||
/* if we can't make if locally, try it in the global place */
|
||||
if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_FILE_EXISTS) {
|
||||
g_free (thumbnail_uri);
|
||||
local_flag = FALSE;
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, TRUE, local_flag);
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, TRUE, local_flag, anti_aliased);
|
||||
result = gnome_vfs_make_directory (thumbnail_uri, THUMBNAIL_DIR_PERMISSIONS);
|
||||
}
|
||||
|
||||
|
@ -1309,6 +1326,7 @@ nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file)
|
|||
NautilusThumbnailInfo *info = g_new0 (NautilusThumbnailInfo, 1);
|
||||
info->thumbnail_uri = file_uri;
|
||||
info->is_local = local_flag;
|
||||
info->anti_aliased = anti_aliased;
|
||||
|
||||
factory = nautilus_get_current_icon_factory ();
|
||||
if (factory->thumbnails) {
|
||||
|
@ -2276,7 +2294,7 @@ check_for_thumbnails (NautilusIconFactory *factory)
|
|||
next_thumbnail != NULL;
|
||||
next_thumbnail = next_thumbnail->next) {
|
||||
info = (NautilusThumbnailInfo*) next_thumbnail->data;
|
||||
current_thumbnail = make_thumbnail_path (info->thumbnail_uri, FALSE, info->is_local);
|
||||
current_thumbnail = make_thumbnail_path (info->thumbnail_uri, FALSE, info->is_local, info->anti_aliased);
|
||||
if (vfs_file_exists (current_thumbnail)) {
|
||||
/* we found one, so update the icon and remove all of the elements up to and including
|
||||
this one from the pending list. */
|
||||
|
@ -2306,6 +2324,19 @@ check_for_thumbnails (NautilusIconFactory *factory)
|
|||
|
||||
/* make_thumbnails is invoked periodically as a timer task to launch a task to make thumbnails */
|
||||
|
||||
static GdkPixbuf*
|
||||
load_thumbnail_frame (gboolean anti_aliased)
|
||||
{
|
||||
char *image_path;
|
||||
GdkPixbuf *frame_image;
|
||||
|
||||
/* load the thumbnail frame */
|
||||
image_path = nautilus_pixmap_file (anti_aliased ? "thumbnail_frame.aa.png" : "thumbnail_frame.png");
|
||||
frame_image = gdk_pixbuf_new_from_file (image_path);
|
||||
g_free (image_path);
|
||||
return frame_image;
|
||||
}
|
||||
|
||||
static int
|
||||
nautilus_icon_factory_make_thumbnails (gpointer data)
|
||||
{
|
||||
|
@ -2313,6 +2344,7 @@ nautilus_icon_factory_make_thumbnails (gpointer data)
|
|||
NautilusThumbnailInfo *info;
|
||||
NautilusIconFactory *factory = nautilus_get_current_icon_factory();
|
||||
GList *next_thumbnail = factory->thumbnails;
|
||||
GdkPixbuf *scaled_image, *framed_image, *thumbnail_image_frame;
|
||||
|
||||
/* if the queue is empty, there's nothing more to do */
|
||||
if (next_thumbnail == NULL) {
|
||||
|
@ -2335,7 +2367,7 @@ nautilus_icon_factory_make_thumbnails (gpointer data)
|
|||
|
||||
/* First, compute the path name of the target thumbnail */
|
||||
g_free (factory->new_thumbnail_path);
|
||||
factory->new_thumbnail_path = make_thumbnail_path (info->thumbnail_uri, FALSE, info->is_local);
|
||||
factory->new_thumbnail_path = make_thumbnail_path (info->thumbnail_uri, FALSE, info->is_local, info->anti_aliased);
|
||||
|
||||
/* fork a task to make the thumbnail, using gdk-pixbuf to do the scaling */
|
||||
if (!(thumbnail_pid = fork())) {
|
||||
|
@ -2361,24 +2393,18 @@ nautilus_icon_factory_make_thumbnails (gpointer data)
|
|||
}
|
||||
nautilus_file_unref (file);
|
||||
|
||||
if (full_size_image != NULL) {
|
||||
GdkPixbuf *scaled_image, *framed_image;
|
||||
int scaled_width, scaled_height;
|
||||
|
||||
if (full_size_image != NULL) {
|
||||
thumbnail_image_frame = load_thumbnail_frame(info->anti_aliased);
|
||||
|
||||
/* scale the content image as necessary */
|
||||
scaled_image = nautilus_gdk_pixbuf_scale_to_fit(full_size_image, 96, 96);
|
||||
scaled_width = gdk_pixbuf_get_width (scaled_image);
|
||||
scaled_height = gdk_pixbuf_get_height (scaled_image);
|
||||
|
||||
/* make the frame to mount it in - use an alpha channel, so part of the drop shadow can be transparent */
|
||||
framed_image = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
|
||||
TRUE, 8,
|
||||
scaled_width + 16, scaled_height + 16);
|
||||
nautilus_draw_frame(framed_image);
|
||||
/* embed the content image in the frame */
|
||||
/* FIXME: the offset numbers are dependent on the frame image - we need to make them adjustable */
|
||||
framed_image = nautilus_embed_image_in_frame (scaled_image, thumbnail_image_frame, 4, 4, 9, 7);
|
||||
|
||||
/* copy the scaled image into it, then release it */
|
||||
gdk_pixbuf_copy_area (scaled_image, 0, 0,
|
||||
scaled_width, scaled_height, framed_image, 6, 6);
|
||||
gdk_pixbuf_unref (scaled_image);
|
||||
gdk_pixbuf_unref (thumbnail_image_frame);
|
||||
|
||||
thumbnail_path = nautilus_get_local_path_from_uri (factory->new_thumbnail_path);
|
||||
if (!save_pixbuf_to_file (framed_image, thumbnail_path)) {
|
||||
|
@ -2396,10 +2422,10 @@ nautilus_icon_factory_make_thumbnails (gpointer data)
|
|||
|
||||
thumbnail_path = nautilus_get_local_path_from_uri (info->thumbnail_uri);
|
||||
|
||||
/* scale the image, then draw a border and frame */
|
||||
/* scale the image */
|
||||
execlp ("convert", "convert", "-geometry", "96x96", thumbnail_path, temp_str, NULL);
|
||||
g_free (thumbnail_path);
|
||||
g_free (temp_str);
|
||||
|
||||
/* we don't come back from this call, so no point in freeing anything up */
|
||||
}
|
||||
|
||||
_exit(0);
|
||||
|
|
|
@ -26,6 +26,11 @@
|
|||
and selection hilighting */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <libart_lgpl/art_config.h>
|
||||
#include <libart_lgpl/art_rect.h>
|
||||
#include <libart_lgpl/art_rgb.h>
|
||||
|
||||
#include "nautilus-graphic-effects.h"
|
||||
|
||||
/* shared utility to create a new pixbuf from the passed-in one */
|
||||
|
@ -221,92 +226,39 @@ nautilus_create_colorized_pixbuf (GdkPixbuf *src,
|
|||
return dest;
|
||||
}
|
||||
|
||||
/* draw a frame with a drop shadow into the passed in pixbuf */
|
||||
/* utility to stretch a frame to the desired size */
|
||||
/* FIXME: right now it justs does a simple scale - it should do it by replicating the "stretchable" area instead of
|
||||
scaling everything uniformly */
|
||||
|
||||
void
|
||||
nautilus_draw_frame (GdkPixbuf *frame_pixbuf)
|
||||
static GdkPixbuf *
|
||||
stretch_frame_image (GdkPixbuf *frame_image, int left_offset, int top_offset, int right_offset, int bottom_offset, int dest_width, int dest_height)
|
||||
{
|
||||
int index, h_index, last_index, pin_width;
|
||||
int width, height, depth, rowstride, fill_value;
|
||||
guchar *pixels, *temp_pixels;
|
||||
return gdk_pixbuf_scale_simple (frame_image, dest_width, dest_height, GDK_INTERP_BILINEAR);
|
||||
}
|
||||
|
||||
|
||||
/* utility to draw the middle section of the frame in a loop */
|
||||
|
||||
/* draw an arbitrary frame around an image, with the result passed back in a newly allocated pixbuf */
|
||||
GdkPixbuf *
|
||||
nautilus_embed_image_in_frame (GdkPixbuf *source_image, GdkPixbuf *frame_image, int left_offset, int top_offset, int right_offset, int bottom_offset)
|
||||
{
|
||||
GdkPixbuf *result_pixbuf;
|
||||
int source_width, source_height;
|
||||
int dest_width, dest_height;
|
||||
|
||||
width = gdk_pixbuf_get_width (frame_pixbuf);
|
||||
height = gdk_pixbuf_get_height (frame_pixbuf);
|
||||
depth = gdk_pixbuf_get_bits_per_sample (frame_pixbuf);
|
||||
pixels = gdk_pixbuf_get_pixels (frame_pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (frame_pixbuf);
|
||||
source_width = gdk_pixbuf_get_width (source_image);
|
||||
source_height = gdk_pixbuf_get_height (source_image);
|
||||
|
||||
/* loop through the pixbuf a scaleline at a time, drawing the frame */
|
||||
for (index = 0; index < height; index++) {
|
||||
/* special case the first and last few lines to make them dark */
|
||||
fill_value = 239;
|
||||
pin_width = width;
|
||||
last_index = height - index;
|
||||
if (index == 0)
|
||||
fill_value = 0;
|
||||
else if (index > (height - 6)) {
|
||||
fill_value = 107 + (index - (height - 5)) * 37;
|
||||
pin_width = width - (height - index);
|
||||
}
|
||||
/* memset(pixels, fill_value, rowstride); */
|
||||
temp_pixels = pixels;
|
||||
for (h_index = 0; h_index < pin_width; h_index++) {
|
||||
*temp_pixels++ = fill_value;
|
||||
*temp_pixels++ = fill_value;
|
||||
*temp_pixels++ = fill_value;
|
||||
*temp_pixels++ = ((last_index < 6) && ((4 - last_index) > h_index)) ? 0 : 255;
|
||||
}
|
||||
dest_width = source_width + left_offset + right_offset;
|
||||
dest_height = source_height + top_offset + bottom_offset;
|
||||
|
||||
result_pixbuf = stretch_frame_image (frame_image, left_offset, top_offset, right_offset, bottom_offset, dest_width, dest_height);
|
||||
|
||||
/* draw the frame at the edge for each scanline */
|
||||
if (last_index > 5) {
|
||||
temp_pixels = pixels;
|
||||
*temp_pixels++ = 0;
|
||||
*temp_pixels++ = 0;
|
||||
*temp_pixels++ = 0;
|
||||
*temp_pixels++ = 255;
|
||||
}
|
||||
|
||||
pixels += rowstride;
|
||||
|
||||
/* handle the last 5 pixels specially for the drop shadow */
|
||||
|
||||
temp_pixels = pixels - 5*4;
|
||||
/* Finally, copy the source image into the framed area */
|
||||
gdk_pixbuf_copy_area (source_image, 0, 0, source_width, source_height, result_pixbuf, left_offset, top_offset);
|
||||
|
||||
if (last_index > 4) {
|
||||
*temp_pixels++ = 107;
|
||||
*temp_pixels++ = 107;
|
||||
*temp_pixels++ = 107;
|
||||
*temp_pixels++ = 255;
|
||||
} else temp_pixels += 4;
|
||||
|
||||
if (last_index > 3) {
|
||||
*temp_pixels++ = 144;
|
||||
*temp_pixels++ = 144;
|
||||
*temp_pixels++ = 144;
|
||||
*temp_pixels++ = index < 1 ? 0 : 255;
|
||||
} else temp_pixels += 4;
|
||||
|
||||
if (last_index > 2) {
|
||||
*temp_pixels++ = 181;
|
||||
*temp_pixels++ = 181;
|
||||
*temp_pixels++ = 181;
|
||||
*temp_pixels++ = index < 2 ? 0 : 255;
|
||||
} else temp_pixels += 4;
|
||||
|
||||
if (last_index > 1) {
|
||||
*temp_pixels++ = 218;
|
||||
*temp_pixels++ = 218;
|
||||
*temp_pixels++ = 218;
|
||||
*temp_pixels++ = index < 3 ? 0 : 255;
|
||||
} else temp_pixels += 4;
|
||||
|
||||
if (last_index > 0) {
|
||||
*temp_pixels++ = 244;
|
||||
*temp_pixels++ = 244;
|
||||
*temp_pixels++ = 244;
|
||||
*temp_pixels++ = index < 4 ? 0 : 255;
|
||||
}
|
||||
}
|
||||
return result_pixbuf;
|
||||
}
|
||||
|
||||
|
||||
|
@ -371,3 +323,4 @@ nautilus_make_semi_transparent (GdkPixbuf *src)
|
|||
|
||||
return dest_pixbuf;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,8 +41,8 @@ GdkPixbuf* nautilus_create_colorized_pixbuf (GdkPixbuf *source_pixbuf,
|
|||
int green_value,
|
||||
int blue_value);
|
||||
|
||||
/* draw a frame with a drop shadow into the passed-in pixbuf */
|
||||
void nautilus_draw_frame (GdkPixbuf *frame_pixbuf);
|
||||
/* embed in image in a frame */
|
||||
GdkPixbuf *nautilus_embed_image_in_frame (GdkPixbuf *source_image, GdkPixbuf *frame_image, int left_offset, int top_offset, int right_offset, int bottom_offset);
|
||||
|
||||
/* return a semi-transparent pixbuf from the source pixbuf using a checkboard
|
||||
stipple in the alpha channel (so it can be converted to an alpha-less pixmap) */
|
||||
|
|
|
@ -211,7 +211,8 @@ static GtkType nautilus_icon_factory_get_type (void);
|
|||
static void nautilus_icon_factory_initialize_class (NautilusIconFactoryClass *class);
|
||||
static void nautilus_icon_factory_initialize (NautilusIconFactory *factory);
|
||||
static NautilusIconFactory * nautilus_get_current_icon_factory (void);
|
||||
static char * nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file);
|
||||
static char * nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file,
|
||||
gboolean anti_aliased);
|
||||
static NautilusIconFactory * nautilus_icon_factory_new (const char *theme_name);
|
||||
static void nautilus_icon_factory_set_theme (const char *theme_name);
|
||||
static guint nautilus_scalable_icon_hash (gconstpointer p);
|
||||
|
@ -951,7 +952,7 @@ nautilus_icon_factory_get_icon_for_file (NautilusFile *file, const char* modifie
|
|||
if (nautilus_file_get_size (file) < SELF_THUMBNAIL_SIZE_THRESHOLD) {
|
||||
uri = nautilus_file_get_uri (file);
|
||||
} else if (strstr(file_uri, "/.thumbnails/") == NULL) {
|
||||
uri = nautilus_icon_factory_get_thumbnail_uri (file);
|
||||
uri = nautilus_icon_factory_get_thumbnail_uri (file, anti_aliased);
|
||||
}
|
||||
}
|
||||
g_free (mime_type);
|
||||
|
@ -1124,11 +1125,13 @@ nautilus_make_directory_and_parents (GnomeVFSURI *uri, guint permissions)
|
|||
/* utility routine that, given the uri of an image, constructs the uri to the corresponding thumbnail */
|
||||
|
||||
static char *
|
||||
make_thumbnail_path (const char *image_uri, gboolean directory_only, gboolean use_local_directory)
|
||||
make_thumbnail_path (const char *image_uri, gboolean directory_only, gboolean use_local_directory, gboolean anti_aliased)
|
||||
{
|
||||
char *thumbnail_uri, *thumbnail_path;
|
||||
char *directory_name = g_strdup (image_uri);
|
||||
char *last_slash = strrchr (directory_name, '/');
|
||||
char *dot_pos;
|
||||
|
||||
*last_slash = '\0';
|
||||
|
||||
/* either use the local directory or one in the user's home directory, as selected by the passed in flag */
|
||||
|
@ -1156,13 +1159,26 @@ make_thumbnail_path (const char *image_uri, gboolean directory_only, gboolean us
|
|||
char* old_uri = thumbnail_uri;
|
||||
thumbnail_uri = g_strdup_printf ("%s/%s", thumbnail_uri, last_slash + 1);
|
||||
g_free(old_uri);
|
||||
}
|
||||
|
||||
/* append an image suffix if the correct one isn't already present */
|
||||
if (!nautilus_istr_has_suffix (image_uri, ".png") && !directory_only) {
|
||||
char* old_uri = thumbnail_uri;
|
||||
thumbnail_uri = g_strdup_printf ("%s.png", thumbnail_uri);
|
||||
g_free(old_uri);
|
||||
/* append the anti-aliased suffix if necessary */
|
||||
if (anti_aliased) {
|
||||
char *old_uri = thumbnail_uri;
|
||||
dot_pos = strrchr (thumbnail_uri, '.');
|
||||
if (dot_pos) {
|
||||
*dot_pos = '\0';
|
||||
thumbnail_uri = g_strdup_printf ("%s.aa.%s", old_uri, dot_pos + 1);
|
||||
} else {
|
||||
thumbnail_uri = g_strconcat (old_uri, ".aa", NULL);
|
||||
}
|
||||
g_free (old_uri);
|
||||
}
|
||||
|
||||
/* append an image suffix if the correct one isn't already present */
|
||||
if (!nautilus_istr_has_suffix (image_uri, ".png")) {
|
||||
char* old_uri = thumbnail_uri;
|
||||
thumbnail_uri = g_strdup_printf ("%s.png", thumbnail_uri);
|
||||
g_free(old_uri);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (directory_name);
|
||||
|
@ -1210,6 +1226,7 @@ first_file_more_recent(const char* file_uri, const char* other_file_uri)
|
|||
typedef struct {
|
||||
char *thumbnail_uri;
|
||||
gboolean is_local;
|
||||
gboolean anti_aliased;
|
||||
} NautilusThumbnailInfo;
|
||||
|
||||
/* GCompareFunc-style function for comparing NautilusThumbnailInfos.
|
||||
|
@ -1234,7 +1251,7 @@ compare_thumbnail_info (gconstpointer a, gconstpointer b)
|
|||
*/
|
||||
|
||||
static char *
|
||||
nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file)
|
||||
nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file, gboolean anti_aliased)
|
||||
{
|
||||
NautilusIconFactory *factory;
|
||||
GnomeVFSResult result;
|
||||
|
@ -1246,7 +1263,7 @@ nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file)
|
|||
file_uri = nautilus_file_get_uri (file);
|
||||
|
||||
/* compose the uri for the thumbnail locally */
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, FALSE, TRUE);
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, FALSE, TRUE, anti_aliased);
|
||||
|
||||
/* if the thumbnail file already exists locally, simply return the uri */
|
||||
if (vfs_file_exists (thumbnail_uri)) {
|
||||
|
@ -1267,7 +1284,7 @@ nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file)
|
|||
/* now try it globally */
|
||||
if (!remake_thumbnail) {
|
||||
g_free (thumbnail_uri);
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, FALSE, FALSE);
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, FALSE, FALSE, anti_aliased);
|
||||
|
||||
/* if the thumbnail file already exists in the common area, return that uri */
|
||||
if (vfs_file_exists (thumbnail_uri)) {
|
||||
|
@ -1289,14 +1306,14 @@ nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file)
|
|||
/* make the thumbnail directory if necessary, at first try it locally */
|
||||
g_free (thumbnail_uri);
|
||||
local_flag = TRUE;
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, TRUE, local_flag);
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, TRUE, local_flag, anti_aliased);
|
||||
result = gnome_vfs_make_directory (thumbnail_uri, THUMBNAIL_DIR_PERMISSIONS);
|
||||
|
||||
/* if we can't make if locally, try it in the global place */
|
||||
if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_FILE_EXISTS) {
|
||||
g_free (thumbnail_uri);
|
||||
local_flag = FALSE;
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, TRUE, local_flag);
|
||||
thumbnail_uri = make_thumbnail_path (file_uri, TRUE, local_flag, anti_aliased);
|
||||
result = gnome_vfs_make_directory (thumbnail_uri, THUMBNAIL_DIR_PERMISSIONS);
|
||||
}
|
||||
|
||||
|
@ -1309,6 +1326,7 @@ nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file)
|
|||
NautilusThumbnailInfo *info = g_new0 (NautilusThumbnailInfo, 1);
|
||||
info->thumbnail_uri = file_uri;
|
||||
info->is_local = local_flag;
|
||||
info->anti_aliased = anti_aliased;
|
||||
|
||||
factory = nautilus_get_current_icon_factory ();
|
||||
if (factory->thumbnails) {
|
||||
|
@ -2276,7 +2294,7 @@ check_for_thumbnails (NautilusIconFactory *factory)
|
|||
next_thumbnail != NULL;
|
||||
next_thumbnail = next_thumbnail->next) {
|
||||
info = (NautilusThumbnailInfo*) next_thumbnail->data;
|
||||
current_thumbnail = make_thumbnail_path (info->thumbnail_uri, FALSE, info->is_local);
|
||||
current_thumbnail = make_thumbnail_path (info->thumbnail_uri, FALSE, info->is_local, info->anti_aliased);
|
||||
if (vfs_file_exists (current_thumbnail)) {
|
||||
/* we found one, so update the icon and remove all of the elements up to and including
|
||||
this one from the pending list. */
|
||||
|
@ -2306,6 +2324,19 @@ check_for_thumbnails (NautilusIconFactory *factory)
|
|||
|
||||
/* make_thumbnails is invoked periodically as a timer task to launch a task to make thumbnails */
|
||||
|
||||
static GdkPixbuf*
|
||||
load_thumbnail_frame (gboolean anti_aliased)
|
||||
{
|
||||
char *image_path;
|
||||
GdkPixbuf *frame_image;
|
||||
|
||||
/* load the thumbnail frame */
|
||||
image_path = nautilus_pixmap_file (anti_aliased ? "thumbnail_frame.aa.png" : "thumbnail_frame.png");
|
||||
frame_image = gdk_pixbuf_new_from_file (image_path);
|
||||
g_free (image_path);
|
||||
return frame_image;
|
||||
}
|
||||
|
||||
static int
|
||||
nautilus_icon_factory_make_thumbnails (gpointer data)
|
||||
{
|
||||
|
@ -2313,6 +2344,7 @@ nautilus_icon_factory_make_thumbnails (gpointer data)
|
|||
NautilusThumbnailInfo *info;
|
||||
NautilusIconFactory *factory = nautilus_get_current_icon_factory();
|
||||
GList *next_thumbnail = factory->thumbnails;
|
||||
GdkPixbuf *scaled_image, *framed_image, *thumbnail_image_frame;
|
||||
|
||||
/* if the queue is empty, there's nothing more to do */
|
||||
if (next_thumbnail == NULL) {
|
||||
|
@ -2335,7 +2367,7 @@ nautilus_icon_factory_make_thumbnails (gpointer data)
|
|||
|
||||
/* First, compute the path name of the target thumbnail */
|
||||
g_free (factory->new_thumbnail_path);
|
||||
factory->new_thumbnail_path = make_thumbnail_path (info->thumbnail_uri, FALSE, info->is_local);
|
||||
factory->new_thumbnail_path = make_thumbnail_path (info->thumbnail_uri, FALSE, info->is_local, info->anti_aliased);
|
||||
|
||||
/* fork a task to make the thumbnail, using gdk-pixbuf to do the scaling */
|
||||
if (!(thumbnail_pid = fork())) {
|
||||
|
@ -2361,24 +2393,18 @@ nautilus_icon_factory_make_thumbnails (gpointer data)
|
|||
}
|
||||
nautilus_file_unref (file);
|
||||
|
||||
if (full_size_image != NULL) {
|
||||
GdkPixbuf *scaled_image, *framed_image;
|
||||
int scaled_width, scaled_height;
|
||||
|
||||
if (full_size_image != NULL) {
|
||||
thumbnail_image_frame = load_thumbnail_frame(info->anti_aliased);
|
||||
|
||||
/* scale the content image as necessary */
|
||||
scaled_image = nautilus_gdk_pixbuf_scale_to_fit(full_size_image, 96, 96);
|
||||
scaled_width = gdk_pixbuf_get_width (scaled_image);
|
||||
scaled_height = gdk_pixbuf_get_height (scaled_image);
|
||||
|
||||
/* make the frame to mount it in - use an alpha channel, so part of the drop shadow can be transparent */
|
||||
framed_image = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
|
||||
TRUE, 8,
|
||||
scaled_width + 16, scaled_height + 16);
|
||||
nautilus_draw_frame(framed_image);
|
||||
/* embed the content image in the frame */
|
||||
/* FIXME: the offset numbers are dependent on the frame image - we need to make them adjustable */
|
||||
framed_image = nautilus_embed_image_in_frame (scaled_image, thumbnail_image_frame, 4, 4, 9, 7);
|
||||
|
||||
/* copy the scaled image into it, then release it */
|
||||
gdk_pixbuf_copy_area (scaled_image, 0, 0,
|
||||
scaled_width, scaled_height, framed_image, 6, 6);
|
||||
gdk_pixbuf_unref (scaled_image);
|
||||
gdk_pixbuf_unref (thumbnail_image_frame);
|
||||
|
||||
thumbnail_path = nautilus_get_local_path_from_uri (factory->new_thumbnail_path);
|
||||
if (!save_pixbuf_to_file (framed_image, thumbnail_path)) {
|
||||
|
@ -2396,10 +2422,10 @@ nautilus_icon_factory_make_thumbnails (gpointer data)
|
|||
|
||||
thumbnail_path = nautilus_get_local_path_from_uri (info->thumbnail_uri);
|
||||
|
||||
/* scale the image, then draw a border and frame */
|
||||
/* scale the image */
|
||||
execlp ("convert", "convert", "-geometry", "96x96", thumbnail_path, temp_str, NULL);
|
||||
g_free (thumbnail_path);
|
||||
g_free (temp_str);
|
||||
|
||||
/* we don't come back from this call, so no point in freeing anything up */
|
||||
}
|
||||
|
||||
_exit(0);
|
||||
|
|
Loading…
Reference in a new issue