diff --git a/libgnome-desktop/gnome-bg.c b/libgnome-desktop/gnome-bg.c
index a882551..a539e06 100644
--- a/libgnome-desktop/gnome-bg.c
+++ b/libgnome-desktop/gnome-bg.c
@@ -144,10 +144,11 @@ static GdkPixbuf *pixbuf_scale_to_fit (GdkPixbuf *src,
static GdkPixbuf *pixbuf_scale_to_min (GdkPixbuf *src,
int min_width,
int min_height);
-static void pixbuf_draw_gradient (GdkPixbuf *pixbuf,
- gboolean horizontal,
- GdkColor *c1,
- GdkColor *c2);
+static void pixbuf_draw_gradient (GdkPixbuf *pixbuf,
+ gboolean horizontal,
+ GdkColor *c1,
+ GdkColor *c2,
+ GdkRectangle *rect);
static void pixbuf_tile (GdkPixbuf *src,
GdkPixbuf *dest);
static void pixbuf_blend (GdkPixbuf *src,
@@ -168,7 +169,9 @@ static gboolean get_thumb_annotations (GdkPixbuf *thumb,
int *orig_height);
/* Cache */
-static GdkPixbuf *get_pixbuf (GnomeBG *bg);
+static GdkPixbuf *get_pixbuf_for_size (GnomeBG *bg,
+ int width,
+ int height);
static void clear_cache (GnomeBG *bg);
static gboolean is_different (GnomeBG *bg,
const char *filename);
@@ -183,7 +186,11 @@ static SlideShow * get_as_slideshow (GnomeBG *bg,
const char *filename);
static Slide * get_current_slide (SlideShow *show,
double *alpha);
-static gboolean slideshow_changes_with_size (SlideShow *show);
+static gboolean slideshow_has_multiple_sizes (SlideShow *show);
+
+static FileSize *find_best_size (GSList *sizes,
+ gint width,
+ gint height);
static void
color_from_string (const char *string,
@@ -613,13 +620,15 @@ gnome_bg_set_filename (GnomeBG *bg,
}
static void
-draw_color (GnomeBG *bg, GdkPixbuf *dest)
+draw_color_area (GnomeBG *bg,
+ GdkPixbuf *dest,
+ GdkRectangle *rect)
{
guint32 pixel;
- switch (bg->color_type)
- {
+ switch (bg->color_type) {
case GNOME_BG_COLOR_SOLID:
+ /* not really a big deal to ignore the area of interest */
pixel = ((bg->primary.red >> 8) << 24) |
((bg->primary.green >> 8) << 16) |
((bg->primary.blue >> 8) << 8) |
@@ -629,11 +638,11 @@ draw_color (GnomeBG *bg, GdkPixbuf *dest)
break;
case GNOME_BG_COLOR_H_GRADIENT:
- pixbuf_draw_gradient (dest, TRUE, &(bg->primary), &(bg->secondary));
+ pixbuf_draw_gradient (dest, TRUE, &(bg->primary), &(bg->secondary), rect);
break;
case GNOME_BG_COLOR_V_GRADIENT:
- pixbuf_draw_gradient (dest, FALSE, &(bg->primary), &(bg->secondary));
+ pixbuf_draw_gradient (dest, FALSE, &(bg->primary), &(bg->secondary), rect);
break;
default:
@@ -641,14 +650,77 @@ draw_color (GnomeBG *bg, GdkPixbuf *dest)
}
}
+static void
+draw_color (GnomeBG *bg,
+ GdkPixbuf *dest,
+ GdkScreen *screen)
+{
+ GdkRectangle rect;
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = gdk_pixbuf_get_width (dest);
+ rect.height = gdk_pixbuf_get_height (dest);
+ draw_color_area (bg, dest, &rect);
+}
+
+static void
+draw_color_each_monitor (GnomeBG *bg,
+ GdkPixbuf *dest,
+ GdkScreen *screen)
+{
+ GdkRectangle rect;
+ gint num_monitors;
+ int monitor;
+
+ num_monitors = gdk_screen_get_n_monitors (screen);
+ for (monitor = 0; monitor < num_monitors; monitor++) {
+ gdk_screen_get_monitor_geometry (screen, monitor, &rect);
+ draw_color_area (bg, dest, &rect);
+ }
+}
+
+static GdkPixbuf *
+pixbuf_clip_to_fit (GdkPixbuf *src,
+ int max_width,
+ int max_height)
+{
+ int src_width, src_height;
+ int w, h;
+ int src_x, src_y;
+ GdkPixbuf *pixbuf;
+
+ src_width = gdk_pixbuf_get_width (src);
+ src_height = gdk_pixbuf_get_height (src);
+
+ if (src_width < max_width && src_height < max_height)
+ return g_object_ref (src);
+
+ w = MIN(src_width, max_width);
+ h = MIN(src_height, max_height);
+
+ pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+ gdk_pixbuf_get_has_alpha (src),
+ 8, w, h);
+
+ src_x = (src_width - w) / 2;
+ src_y = (src_height - h) / 2;
+ gdk_pixbuf_copy_area (src,
+ src_x, src_y,
+ w, h,
+ pixbuf,
+ 0, 0);
+ return pixbuf;
+}
+
static GdkPixbuf *
get_scaled_pixbuf (GnomeBGPlacement placement,
GdkPixbuf *pixbuf,
int width, int height,
- int *x, int *y, int *w, int *h)
+ int *x, int *y,
+ int *w, int *h)
{
GdkPixbuf *new;
-
+
#if 0
g_print ("original_width: %d %d\n",
gdk_pixbuf_get_width (pixbuf),
@@ -672,7 +744,7 @@ get_scaled_pixbuf (GnomeBGPlacement placement,
case GNOME_BG_PLACEMENT_CENTERED:
case GNOME_BG_PLACEMENT_TILED:
default:
- new = g_object_ref (pixbuf);
+ new = pixbuf_clip_to_fit (pixbuf, width, height);
break;
}
@@ -685,20 +757,20 @@ get_scaled_pixbuf (GnomeBGPlacement placement,
}
static void
-draw_image (GnomeBGPlacement placement,
- GdkPixbuf *pixbuf,
- GdkPixbuf *dest)
+draw_image_area (GnomeBGPlacement placement,
+ GdkPixbuf *pixbuf,
+ GdkPixbuf *dest,
+ GdkRectangle *area)
{
- int dest_width = gdk_pixbuf_get_width (dest);
- int dest_height = gdk_pixbuf_get_height (dest);
+ int dest_width = area->width;
+ int dest_height = area->height;
int x, y, w, h;
GdkPixbuf *scaled;
if (!pixbuf)
return;
-
- scaled = get_scaled_pixbuf (
- placement, pixbuf, dest_width, dest_height, &x, &y, &w, &h);
+
+ scaled = get_scaled_pixbuf (placement, pixbuf, dest_width, dest_height, &x, &y, &w, &h);
switch (placement) {
case GNOME_BG_PLACEMENT_TILED:
@@ -708,7 +780,7 @@ draw_image (GnomeBGPlacement placement,
case GNOME_BG_PLACEMENT_CENTERED:
case GNOME_BG_PLACEMENT_FILL_SCREEN:
case GNOME_BG_PLACEMENT_SCALED:
- pixbuf_blend (scaled, dest, 0, 0, w, h, x, y, 1.0);
+ pixbuf_blend (scaled, dest, 0, 0, w, h, x + area->x, y + area->y, 1.0);
break;
default:
g_assert_not_reached ();
@@ -718,54 +790,97 @@ draw_image (GnomeBGPlacement placement,
g_object_unref (scaled);
}
+static void
+draw_image (GnomeBGPlacement placement,
+ GdkPixbuf *pixbuf,
+ GdkPixbuf *dest)
+{
+ GdkRectangle rect;
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = gdk_pixbuf_get_width (dest);
+ rect.height = gdk_pixbuf_get_height (dest);
+
+ draw_image_area (placement, pixbuf, dest, &rect);
+}
+
+static void
+draw_once (GnomeBG *bg,
+ GdkPixbuf *dest,
+ GdkScreen *screen)
+{
+ GdkRectangle rect;
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = gdk_pixbuf_get_width (dest);
+ rect.height = gdk_pixbuf_get_height (dest);
+
+ draw_image_area (bg->placement,
+ get_pixbuf_for_size (bg, gdk_pixbuf_get_width (dest), gdk_pixbuf_get_height (dest)),
+ dest,
+ &rect);
+}
+
+static void
+draw_each_monitor (GnomeBG *bg,
+ GdkPixbuf *dest,
+ GdkScreen *screen)
+{
+ GdkRectangle rect;
+ gint num_monitors;
+ int monitor;
+
+ num_monitors = gdk_screen_get_n_monitors (screen);
+ for (monitor = 0; monitor < num_monitors; monitor++) {
+ gdk_screen_get_monitor_geometry (screen, monitor, &rect);
+ draw_image_area (bg->placement,
+ get_pixbuf_for_size (bg, rect.width, rect.height),
+ dest, &rect);
+ }
+}
+
void
-gnome_bg_draw (GnomeBG *bg, GdkPixbuf *dest)
+gnome_bg_draw (GnomeBG *bg,
+ GdkPixbuf *dest,
+ GdkScreen *screen,
+ gboolean is_root)
{
if (!bg)
return;
-
- draw_color (bg, dest);
-
- draw_image (bg->placement, get_pixbuf (bg), dest);
+
+ if (is_root) {
+ draw_color_each_monitor (bg, dest, screen);
+ draw_each_monitor (bg, dest, screen);
+ } else {
+ draw_color (bg, dest, screen);
+ draw_once (bg, dest, screen);
+ }
}
gboolean
-gnome_bg_changes_with_size (GnomeBG *bg)
+gnome_bg_has_multiple_sizes (GnomeBG *bg)
{
SlideShow *show;
g_return_val_if_fail (bg != NULL, FALSE);
show = get_as_slideshow (bg, bg->filename);
- if (show)
- return slideshow_changes_with_size (show);
-
- if (bg->color_type != GNOME_BG_COLOR_SOLID) {
- if (!get_pixbuf (bg))
- return TRUE;
- if (gdk_pixbuf_get_has_alpha (get_pixbuf (bg)))
- return TRUE;
- if (bg->placement == GNOME_BG_PLACEMENT_CENTERED)
- return TRUE;
- return FALSE;
- }
- else if (bg->placement == GNOME_BG_PLACEMENT_TILED) {
- return FALSE;
- }
- else {
- return TRUE;
- }
+ if (show)
+ return slideshow_has_multiple_sizes (show);
+
+ return FALSE;
}
static void
-gnome_bg_get_pixmap_size (GnomeBG *bg,
- int width,
- int height,
- int *pixmap_width,
- int *pixmap_height)
+gnome_bg_get_pixmap_size (GnomeBG *bg,
+ int width,
+ int height,
+ int *pixmap_width,
+ int *pixmap_height)
{
int dummy;
- int pb_width, pb_height;
if (!pixmap_width)
pixmap_width = &dummy;
@@ -774,8 +889,8 @@ gnome_bg_get_pixmap_size (GnomeBG *bg,
*pixmap_width = width;
*pixmap_height = height;
-
- if (!get_pixbuf (bg)) {
+
+ if (!bg->filename) {
switch (bg->color_type) {
case GNOME_BG_COLOR_SOLID:
*pixmap_width = 1;
@@ -783,44 +898,12 @@ gnome_bg_get_pixmap_size (GnomeBG *bg,
break;
case GNOME_BG_COLOR_H_GRADIENT:
- *pixmap_width = width;
- *pixmap_height = GRADIENT_PIXMAP_TILE_SIZE;
- break;
-
case GNOME_BG_COLOR_V_GRADIENT:
- *pixmap_width = GRADIENT_PIXMAP_TILE_SIZE;
- *pixmap_height = height;
break;
}
return;
}
-
- pb_width = gdk_pixbuf_get_width (get_pixbuf (bg));
- pb_height = gdk_pixbuf_get_height (get_pixbuf (bg));
-
- if (bg->placement == GNOME_BG_PLACEMENT_TILED) {
- if (gdk_pixbuf_get_has_alpha (get_pixbuf (bg)) &&
- bg->color_type != GNOME_BG_COLOR_SOLID) {
- if (bg->color_type == GNOME_BG_COLOR_H_GRADIENT) {
- /* FIXME: Should this be
- * MAX (GRADIENT_TILE_SIZE, pb_height)?
- */
- *pixmap_height = pb_height;
- *pixmap_width = width;
- }
- else {
- /* FIXME: Should this be
- * MAX (GRAIDENT_TILE_SIZE, pb_width? */
- *pixmap_width = pb_width;
- *pixmap_height = height;
- }
- }
- else {
- *pixmap_width = pb_width;
- *pixmap_height = pb_height;
- }
- }
}
/**
@@ -842,7 +925,7 @@ gnome_bg_create_pixmap (GnomeBG *bg,
GdkWindow *window,
int width,
int height,
- gboolean root)
+ gboolean is_root)
{
int pm_width, pm_height;
GdkPixmap *pixmap;
@@ -860,9 +943,10 @@ gnome_bg_create_pixmap (GnomeBG *bg,
bg->last_pixmap_width = width;
bg->last_pixmap_height = height;
+ /* has the side effect of loading and caching pixbuf only when in tile mode */
gnome_bg_get_pixmap_size (bg, width, height, &pm_width, &pm_height);
- if (root) {
+ if (is_root) {
pixmap = make_root_pixmap (gdk_drawable_get_screen (window),
pm_width, pm_height);
}
@@ -870,7 +954,7 @@ gnome_bg_create_pixmap (GnomeBG *bg,
pixmap = gdk_pixmap_new (window, pm_width, pm_height, -1);
}
- if (!get_pixbuf (bg) && bg->color_type == GNOME_BG_COLOR_SOLID) {
+ if (!bg->filename && bg->color_type == GNOME_BG_COLOR_SOLID) {
GdkGC *gc = gdk_gc_new (pixmap);
gdk_gc_set_rgb_fg_color (gc, &(bg->primary));
@@ -883,7 +967,7 @@ gnome_bg_create_pixmap (GnomeBG *bg,
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
width, height);
- gnome_bg_draw (bg, pixbuf);
+ gnome_bg_draw (bg, pixbuf, gdk_drawable_get_screen (GDK_DRAWABLE (window)), is_root);
gdk_draw_pixbuf (pixmap, NULL, pixbuf,
0, 0,
0, 0, width, height,
@@ -899,10 +983,13 @@ gnome_bg_create_pixmap (GnomeBG *bg,
* clients know what colors to draw on top with
*/
gboolean
-gnome_bg_is_dark (GnomeBG *bg)
+gnome_bg_is_dark (GnomeBG *bg,
+ int width,
+ int height)
{
GdkColor color;
int intensity;
+ GdkPixbuf *pixbuf;
g_return_val_if_fail (bg != NULL, FALSE);
@@ -913,9 +1000,9 @@ gnome_bg_is_dark (GnomeBG *bg)
color.green = (bg->primary.green + bg->secondary.green) / 2;
color.blue = (bg->primary.blue + bg->secondary.blue) / 2;
}
-
- if (get_pixbuf (bg)) {
- guint32 argb = pixbuf_average_value (get_pixbuf (bg));
+ pixbuf = get_pixbuf_for_size (bg, width, height);
+ if (pixbuf) {
+ guint32 argb = pixbuf_average_value (pixbuf);
guchar a = (argb >> 24) & 0xff;
guchar r = (argb >> 16) & 0xff;
guchar g = (argb >> 8) & 0xff;
@@ -1001,9 +1088,31 @@ get_original_size (const char *filename,
return result;
}
+static const char *
+get_filename_for_size (GnomeBG *bg, gint best_width, gint best_height)
+{
+ SlideShow *show;
+ Slide *slide;
+ FileSize *size;
+
+ if (!bg->filename)
+ return NULL;
+
+ show = get_as_slideshow (bg, bg->filename);
+ if (!show) {
+ return bg->filename;
+ }
+
+ slide = get_current_slide (show, NULL);
+ size = find_best_size (slide->file1, best_width, best_height);
+ return size->file;
+}
+
gboolean
gnome_bg_get_image_size (GnomeBG *bg,
GnomeDesktopThumbnailFactory *factory,
+ int best_width,
+ int best_height,
int *width,
int *height)
{
@@ -1017,21 +1126,8 @@ gnome_bg_get_image_size (GnomeBG *bg,
if (!bg->filename)
return FALSE;
- filename = bg->filename;
+ filename = get_filename_for_size (bg, best_width, best_height);
thumb = create_thumbnail_for_filename (factory, filename);
-
- if (!thumb) {
- SlideShow *show = get_as_slideshow (bg, bg->filename);
- if (show) {
- double alpha;
- FileSize *fs;
- Slide *slide = get_current_slide (show, &alpha);
- fs = slide->file1->data;
- filename = fs->file;
- thumb = create_thumbnail_for_filename (factory, filename);
- }
- }
-
if (thumb) {
if (get_thumb_annotations (thumb, width, height))
result = TRUE;
@@ -1068,7 +1164,7 @@ gnome_bg_create_thumbnail (GnomeBG *bg,
result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, dest_width, dest_height);
- draw_color (bg, result);
+ draw_color (bg, result, screen);
thumb = create_img_thumbnail (bg, factory, screen, dest_width, dest_height, -1);
@@ -1316,7 +1412,7 @@ struct _SlideShow
GQueue *slides;
- gboolean changes_with_size;
+ gboolean has_multiple_sizes;
/* used during parsing */
struct tm start_tm;
@@ -1356,7 +1452,8 @@ get_current_slide (SlideShow *show,
Slide *slide = list->data;
if (elapsed + slide->duration > delta) {
- *alpha = (delta - elapsed) / (double)slide->duration;
+ if (alpha)
+ *alpha = (delta - elapsed) / (double)slide->duration;
return slide;
}
@@ -1512,7 +1609,10 @@ file_cache_add_slide_show (GnomeBG *bg,
}
static GdkPixbuf *
-get_as_pixbuf (GnomeBG *bg, const char *filename)
+get_as_pixbuf_for_size (GnomeBG *bg,
+ const char *filename,
+ int best_width,
+ int best_height)
{
const FileCacheEntry *ent;
if ((ent = file_cache_lookup (bg, PIXBUF, filename))) {
@@ -1523,14 +1623,14 @@ get_as_pixbuf (GnomeBG *bg, const char *filename)
GdkPixbuf *pixbuf;
/* If scalable choose maximum size */
- format = gdk_pixbuf_get_file_info (bg->filename, NULL, NULL);
+ format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
if (format != NULL &&
strcmp (gdk_pixbuf_format_get_name (format), "svg") == 0 &&
- (bg->last_pixmap_width > 0 && bg->last_pixmap_height > 0) &&
+ (best_width > 0 && best_height > 0) &&
(bg->placement == GNOME_BG_PLACEMENT_FILL_SCREEN ||
bg->placement == GNOME_BG_PLACEMENT_SCALED ||
bg->placement == GNOME_BG_PLACEMENT_ZOOMED))
- pixbuf = gdk_pixbuf_new_from_file_at_size (filename, bg->last_pixmap_width, bg->last_pixmap_height, NULL);
+ pixbuf = gdk_pixbuf_new_from_file_at_size (filename, best_width, best_height, NULL);
else
pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
@@ -1763,9 +1863,8 @@ create_img_thumbnail (GnomeBG *bg,
GdkPixbuf *thumb = get_as_thumbnail (bg, factory, bg->filename);
if (thumb) {
- return scale_thumbnail (
- bg->placement, bg->filename,
- thumb, screen, dest_width, dest_height);
+ return scale_thumbnail (bg->placement, bg->filename,
+ thumb, screen, dest_width, dest_height);
}
else {
SlideShow *show = get_as_slideshow (bg, bg->filename);
@@ -1784,36 +1883,29 @@ create_img_thumbnail (GnomeBG *bg,
if (slide->fixed) {
GdkPixbuf *tmp;
FileSize *fs;
-
- fs = slide->file1->data;
+ fs = find_best_size (slide->file1, dest_width, dest_height);
tmp = get_as_thumbnail (bg, factory, fs->file);
-
- thumb = scale_thumbnail (
- bg->placement, fs->file,
- tmp, screen, dest_width, dest_height);
+ if (tmp)
+ thumb = scale_thumbnail (bg->placement, fs->file,
+ tmp, screen, dest_width, dest_height);
}
else {
- FileSize *fs;
+ FileSize *fs1, *fs2;
GdkPixbuf *p1, *p2;
+ fs1 = find_best_size (slide->file1, dest_width, dest_height);
+ p1 = get_as_thumbnail (bg, factory, fs1->file);
- fs = slide->file1->data;
- p1 = get_as_thumbnail (bg, factory, fs->file);
-
- fs = slide->file2->data;
- p2 = get_as_thumbnail (bg, factory, fs->file);
+ fs2 = find_best_size (slide->file2, dest_width, dest_height);
+ p2 = get_as_thumbnail (bg, factory, fs2->file);
if (p1 && p2) {
GdkPixbuf *thumb1, *thumb2;
- fs = slide->file1->data;
- thumb1 = scale_thumbnail (
- bg->placement, fs->file,
- p1, screen, dest_width, dest_height);
+ thumb1 = scale_thumbnail (bg->placement, fs1->file,
+ p1, screen, dest_width, dest_height);
- fs = slide->file2->data;
- thumb2 = scale_thumbnail (
- bg->placement, fs->file,
- p2, screen, dest_width, dest_height);
+ thumb2 = scale_thumbnail (bg->placement, fs2->file,
+ p2, screen, dest_width, dest_height);
thumb = blend (thumb1, thumb2, alpha);
@@ -1880,18 +1972,26 @@ find_best_size (GSList *sizes, gint width, gint height)
}
static GdkPixbuf *
-get_pixbuf (GnomeBG *bg)
+get_pixbuf_for_size (GnomeBG *bg, gint best_width, gint best_height)
{
/* FIXME: this ref=TRUE/FALSE stuff is crazy */
-
guint time_until_next_change;
gboolean ref = FALSE;
-
- if (!bg->pixbuf_cache && bg->filename) {
+ gboolean hit_cache = FALSE;
+
+ /* only hit the cache if the aspect ratio matches */
+ if (bg->pixbuf_cache) {
+ int width, height;
+ width = gdk_pixbuf_get_width (bg->pixbuf_cache);
+ height = gdk_pixbuf_get_height (bg->pixbuf_cache);
+ hit_cache = 0.2 > fabs ((best_width / (double)best_height) - (width / (double)height));
+ }
+
+ if (!hit_cache && bg->filename) {
ref = TRUE;
bg->file_mtime = get_mtime (bg->filename);
- bg->pixbuf_cache = get_as_pixbuf (bg, bg->filename);
+ bg->pixbuf_cache = get_as_pixbuf_for_size (bg, bg->filename, best_width, best_height);
time_until_next_change = G_MAXUINT;
if (!bg->pixbuf_cache) {
SlideShow *show = get_as_slideshow (bg, bg->filename);
@@ -1906,16 +2006,16 @@ get_pixbuf (GnomeBG *bg)
time_until_next_change = (guint)get_slide_timeout (slide);
if (slide->fixed) {
FileSize *size;
- size = find_best_size (slide->file1, bg->last_pixmap_width, bg->last_pixmap_height);
- bg->pixbuf_cache = get_as_pixbuf (bg, size->file);
+ size = find_best_size (slide->file1, best_width, best_height);
+ bg->pixbuf_cache = get_as_pixbuf_for_size (bg, size->file, best_width, best_height);
}
else {
FileSize *size;
GdkPixbuf *p1, *p2;
- size = find_best_size (slide->file1, bg->last_pixmap_width, bg->last_pixmap_height);
- p1 = get_as_pixbuf (bg, size->file);
- size = find_best_size (slide->file2, bg->last_pixmap_width, bg->last_pixmap_height);
- p2 = get_as_pixbuf (bg, size->file);
+ size = find_best_size (slide->file1, best_width, best_height);
+ p1 = get_as_pixbuf_for_size (bg, size->file, best_width, best_height);
+ size = find_best_size (slide->file2, best_width, best_height);
+ p2 = get_as_pixbuf_for_size (bg, size->file, best_width, best_height);
if (p1 && p2) {
@@ -2084,22 +2184,38 @@ pixbuf_scale_to_min (GdkPixbuf *src, int min_width, int min_height)
double factor;
int src_width, src_height;
int new_width, new_height;
-
+ GdkPixbuf *dest;
+
src_width = gdk_pixbuf_get_width (src);
src_height = gdk_pixbuf_get_height (src);
-
+
factor = MAX (min_width / (double) src_width, min_height / (double) src_height);
-
+
new_width = floor (src_width * factor + 0.5);
new_height = floor (src_height * factor + 0.5);
-
- return gdk_pixbuf_scale_simple (src, new_width, new_height, GDK_INTERP_BILINEAR);
+
+ dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+ gdk_pixbuf_get_has_alpha (src),
+ 8, min_width, min_height);
+ if (!dest)
+ return NULL;
+
+ /* crop the result */
+ gdk_pixbuf_scale (src, dest,
+ 0, 0,
+ min_width, min_height,
+ (new_width - min_width) / -2,
+ (new_height - min_height) / -2,
+ factor,
+ factor,
+ GDK_INTERP_BILINEAR);
+ return dest;
}
static guchar *
create_gradient (const GdkColor *primary,
const GdkColor *secondary,
- int n_pixels)
+ int n_pixels)
{
guchar *result = g_malloc (n_pixels * 3);
int i;
@@ -2116,43 +2232,56 @@ create_gradient (const GdkColor *primary,
}
static void
-pixbuf_draw_gradient (GdkPixbuf *pixbuf,
- gboolean horizontal,
- GdkColor *primary,
- GdkColor *secondary)
-{
- int width = gdk_pixbuf_get_width (pixbuf);
- int height = gdk_pixbuf_get_height (pixbuf);
- int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
- guchar *dst = gdk_pixbuf_get_pixels (pixbuf);
- guchar *dst_limit = dst + height * rowstride;
-
+pixbuf_draw_gradient (GdkPixbuf *pixbuf,
+ gboolean horizontal,
+ GdkColor *primary,
+ GdkColor *secondary,
+ GdkRectangle *rect)
+{
+ int width;
+ int height;
+ int rowstride;
+ guchar *dst;
+ guchar *dst_limit;
+ int n_channels = 3;
+
+ rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+ width = rect->width;
+ height = rect->height;
+ dst = gdk_pixbuf_get_pixels (pixbuf) + rect->x * n_channels + rowstride * rect->y;
+ dst_limit = dst + height * rowstride;
+
if (horizontal) {
guchar *gradient = create_gradient (primary, secondary, width);
- int copy_bytes_per_row = width * 3;
-
- while (dst < dst_limit) {
- memcpy (dst, gradient, copy_bytes_per_row);
- dst += rowstride;
+ int copy_bytes_per_row = width * n_channels;
+ int i;
+
+ for (i = 0; i < height; i++) {
+ guchar *d;
+ d = dst + rowstride * i;
+ memcpy (d, gradient, copy_bytes_per_row);
}
g_free (gradient);
} else {
guchar *gb, *gradient;
-
- gb = gradient = create_gradient (primary, secondary, height);
- while (dst < dst_limit) {
- int i;
- guchar *d = dst;
- guchar r = *gb++;
- guchar g = *gb++;
- guchar b = *gb++;
- for (i = 0; i < width; i++) {
- *d++ = r;
- *d++ = g;
- *d++ = b;
+ int i;
+
+ gradient = create_gradient (primary, secondary, height);
+ for (i = 0; i < height; i++) {
+ int j;
+ guchar *d;
+
+ d = dst + rowstride * i;
+ gb = gradient + n_channels * i;
+ for (j = width; j > 0; j--) {
+ int k;
+
+ for (k = 0; k < n_channels; k++) {
+ *(d++) = gb[k];
+ }
}
- dst += rowstride;
}
+
g_free (gradient);
}
}
@@ -2162,8 +2291,8 @@ pixbuf_blend (GdkPixbuf *src,
GdkPixbuf *dest,
int src_x,
int src_y,
- int width,
- int height,
+ int src_width,
+ int src_height,
int dest_x,
int dest_y,
double alpha)
@@ -2173,11 +2302,11 @@ pixbuf_blend (GdkPixbuf *src,
int offset_x = dest_x - src_x;
int offset_y = dest_y - src_y;
- if (width < 0)
- width = gdk_pixbuf_get_width (src);
+ if (src_width < 0)
+ src_width = gdk_pixbuf_get_width (src);
- if (height < 0)
- height = gdk_pixbuf_get_height (src);
+ if (src_height < 0)
+ src_height = gdk_pixbuf_get_height (src);
if (dest_x < 0)
dest_x = 0;
@@ -2185,17 +2314,17 @@ pixbuf_blend (GdkPixbuf *src,
if (dest_y < 0)
dest_y = 0;
- if (dest_x + width > dest_width) {
- width = dest_width - dest_x;
+ if (dest_x + src_width > dest_width) {
+ src_width = dest_width - dest_x;
}
- if (dest_y + height > dest_height) {
- height = dest_height - dest_y;
+ if (dest_y + src_height > dest_height) {
+ src_height = dest_height - dest_y;
}
gdk_pixbuf_composite (src, dest,
dest_x, dest_y,
- width, height,
+ src_width, src_height,
offset_x, offset_y,
1, 1, GDK_INTERP_NEAREST,
alpha * 0xFF + 0.5);
@@ -2368,14 +2497,14 @@ handle_text (GMarkupParseContext *context,
fs->file = g_strdup (text);
slide->file1 = g_slist_prepend (slide->file1, fs);
if (slide->file1->next != NULL)
- parser->changes_with_size = TRUE;
+ parser->has_multiple_sizes = TRUE;
}
else if (stack_is (parser, "size", "file", "static", "background", NULL) ||
stack_is (parser, "size", "from", "transition", "background", NULL)) {
fs = slide->file1->data;
fs->file = g_strdup (text);
if (slide->file1->next != NULL)
- parser->changes_with_size = TRUE;
+ parser->has_multiple_sizes = TRUE;
}
else if (stack_is (parser, "to", "transition", "background", NULL)) {
for (i = 0; text[i]; i++) {
@@ -2390,13 +2519,13 @@ handle_text (GMarkupParseContext *context,
fs->file = g_strdup (text);
slide->file2 = g_slist_prepend (slide->file2, fs);
if (slide->file2->next != NULL)
- parser->changes_with_size = TRUE;
+ parser->has_multiple_sizes = TRUE;
}
else if (stack_is (parser, "size", "to", "transition", "background", NULL)) {
fs = slide->file2->data;
fs->file = g_strdup (text);
if (slide->file2->next != NULL)
- parser->changes_with_size = TRUE;
+ parser->has_multiple_sizes = TRUE;
}
}
@@ -2639,9 +2768,9 @@ get_thumb_annotations (GdkPixbuf *thumb,
}
static gboolean
-slideshow_changes_with_size (SlideShow *show)
+slideshow_has_multiple_sizes (SlideShow *show)
{
- return show->changes_with_size;
+ return show->has_multiple_sizes;
}
/*
@@ -2712,7 +2841,7 @@ gnome_bg_create_frame_thumbnail (GnomeBG *bg,
result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, dest_width, dest_height);
- draw_color (bg, result);
+ draw_color (bg, result, screen);
thumb = create_img_thumbnail (bg, factory, screen, dest_width, dest_height, frame_num + skipped);
diff --git a/libgnome-desktop/libgnomeui/gnome-bg.h b/libgnome-desktop/libgnomeui/gnome-bg.h
index 993173a..6ab2cb0 100644
--- a/libgnome-desktop/libgnomeui/gnome-bg.h
+++ b/libgnome-desktop/libgnomeui/gnome-bg.h
@@ -87,7 +87,9 @@ const gchar * gnome_bg_get_filename (GnomeBG *bg);
/* Drawing and thumbnailing */
void gnome_bg_draw (GnomeBG *bg,
- GdkPixbuf *dest);
+ GdkPixbuf *dest,
+ GdkScreen *screen,
+ gboolean is_root);
GdkPixmap * gnome_bg_create_pixmap (GnomeBG *bg,
GdkWindow *window,
int width,
@@ -95,6 +97,8 @@ GdkPixmap * gnome_bg_create_pixmap (GnomeBG *bg,
gboolean root);
gboolean gnome_bg_get_image_size (GnomeBG *bg,
GnomeDesktopThumbnailFactory *factory,
+ int best_width,
+ int best_height,
int *width,
int *height);
GdkPixbuf * gnome_bg_create_thumbnail (GnomeBG *bg,
@@ -102,8 +106,10 @@ GdkPixbuf * gnome_bg_create_thumbnail (GnomeBG *bg,
GdkScreen *screen,
int dest_width,
int dest_height);
-gboolean gnome_bg_is_dark (GnomeBG *bg);
-gboolean gnome_bg_changes_with_size (GnomeBG *bg);
+gboolean gnome_bg_is_dark (GnomeBG *bg,
+ int dest_width,
+ int dest_height);
+gboolean gnome_bg_has_multiple_sizes (GnomeBG *bg);
gboolean gnome_bg_changes_with_time (GnomeBG *bg);
GdkPixbuf * gnome_bg_create_frame_thumbnail (GnomeBG *bg,
GnomeDesktopThumbnailFactory *factory,