--- gnome-desktop-2.23.2/libgnome-desktop/gnome-bg.c.multires 2008-05-14 00:39:32.000000000 -0400
+++ gnome-desktop-2.23.2/libgnome-desktop/gnome-bg.c 2008-05-14 01:03:52.000000000 -0400
@@ -59,8 +59,17 @@ struct _Slide
double duration; /* in seconds */
gboolean fixed;
- char *file1;
- char *file2; /* NULL if fixed is TRUE */
+ GSList *file1;
+ GSList *file2; /* NULL if fixed is TRUE */
+};
+
+typedef struct _FileSize FileSize;
+struct _FileSize
+{
+ gint width;
+ gint height;
+
+ char *file;
};
/* This is the size of the GdkRGB dither matrix, in order to avoid
@@ -83,6 +92,9 @@ struct _GnomeBG
GdkColor c1;
GdkColor c2;
+ gint last_pixmap_width;
+ gint last_pixmap_height;
+
/* Cached information, only access through cache accessor functions */
SlideShow * slideshow;
time_t uri_mtime;
@@ -158,6 +170,7 @@ static SlideShow * get_as_slideshow (
const char *uri);
static Slide * get_current_slide (SlideShow *show,
double *alpha);
+static gboolean slideshow_changes_with_size (SlideShow *show);
static void
set_color_from_string (const char *string,
@@ -512,6 +525,10 @@ gboolean
gnome_bg_changes_with_size (GnomeBG *bg)
{
g_return_val_if_fail (bg != NULL, FALSE);
+
+ SlideShow *show = get_as_slideshow (bg, bg->uri);
+ if (show)
+ return slideshow_changes_with_size (show);
if (bg->color_type != GNOME_BG_COLOR_SOLID) {
if (!get_pixbuf (bg))
@@ -622,7 +639,17 @@ gnome_bg_create_pixmap (GnomeBG *bg,
g_return_val_if_fail (bg != NULL, NULL);
g_return_val_if_fail (window != NULL, NULL);
-
+
+ if (bg->last_pixmap_width != width ||
+ bg->last_pixmap_height != height) {
+ if (bg->pixbuf_cache) {
+ g_object_unref (bg->pixbuf_cache);
+ bg->pixbuf_cache = NULL;
+ }
+ }
+ bg->last_pixmap_width = width;
+ bg->last_pixmap_height = height;
+
gnome_bg_get_pixmap_size (bg, width, height, &pm_width, &pm_height);
if (root) {
@@ -791,8 +818,10 @@ gnome_bg_get_image_size (GnomeBG
SlideShow *show = get_as_slideshow (bg, bg->uri);
if (show) {
double alpha;
+ FileSize *fs;
Slide *slide = get_current_slide (show, &alpha);
- uri = slide->file1;
+ fs = slide->file1->data;
+ uri = fs->file;
thumb = create_thumbnail_for_uri (factory, uri);
}
}
@@ -923,6 +952,8 @@ struct _SlideShow
GQueue *slides;
+ gboolean changes_with_size;
+
/* used during parsing */
struct tm start_tm;
GQueue *stack;
@@ -1298,16 +1329,23 @@ create_img_thumbnail (GnomeBG
if (slide->fixed) {
GdkPixbuf *tmp;
+ FileSize *fs;
- tmp = get_as_thumbnail (bg, factory, slide->file1);
+ fs = slide->file1->data;
+ tmp = get_as_thumbnail (bg, factory, fs->file);
thumb = scale_thumbnail (
bg->placement, bg->uri,
tmp, screen, dest_width, dest_height);
}
else {
- GdkPixbuf *p1 = get_as_thumbnail (bg, factory, slide->file1);
- GdkPixbuf *p2 = get_as_thumbnail (bg, factory, slide->file2);
+ FileSize *fs;
+ GdkPixbuf *p1, *p2;
+
+ fs = slide->file1->data;
+ p1 = get_as_thumbnail (bg, factory, fs->file);
+ fs = slide->file2->data;
+ p2 = get_as_thumbnail (bg, factory, fs->file);
if (p1 && p2) {
GdkPixbuf *thumb1, *thumb2;
@@ -1336,6 +1374,51 @@ create_img_thumbnail (GnomeBG
return NULL;
}
+/*
+ * Find the FileSize that best matches the given size.
+ * Do two passes; the first pass only considers FileSizes
+ * that are larger than the given size.
+ * We are looking for the image that best matches the aspect ratio.
+ * When two images have the same aspect ratio, prefer the one whose
+ * width is closer to the given width.
+ */
+static FileSize *
+find_best_size (GSList *sizes, gint width, gint height)
+{
+ GSList *s;
+ gdouble a, d, distance;
+ FileSize *best = NULL;
+ gint pass;
+
+ a = width/(gdouble)height;
+ distance = 10000.0;
+
+ for (pass = 0; pass < 2; pass++) {
+ for (s = sizes; s; s = s->next) {
+ FileSize *size = s->data;
+
+ if (pass == 0 && (size->width < width || size->height < height))
+ continue;
+
+ d = fabs (a - size->width/(gdouble)size->height);
+ if (d < distance) {
+ distance = d;
+ best = size;
+ }
+ else if (d == distance) {
+ if (abs (size->width - width) < abs (best->width - width)) {
+ best = size;
+ }
+ }
+ }
+
+ if (best)
+ break;
+ }
+
+ return best;
+}
+
static GdkPixbuf *
get_pixbuf (GnomeBG *bg)
{
@@ -1356,11 +1439,18 @@ get_pixbuf (GnomeBG *bg)
Slide *slide = get_current_slide (show, &alpha);
if (slide->fixed) {
- bg->pixbuf_cache = get_as_pixbuf (bg, slide->file1);
+ 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);
}
else {
- GdkPixbuf *p1 = get_as_pixbuf (bg, slide->file1);
- GdkPixbuf *p2 = get_as_pixbuf (bg, slide->file2);
+ 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);
+
if (p1 && p2) {
bg->pixbuf_cache = blend (p1, p2, alpha);
@@ -1656,6 +1746,7 @@ pixbuf_tile (GdkPixbuf *src, GdkPixbuf *
}
}
+static gboolean stack_is (SlideShow *parser, const char *s1, ...);
/* Parser for fading background */
static void
@@ -1667,6 +1758,7 @@ handle_start_element (GMarkupParseContex
GError **err)
{
SlideShow *parser = user_data;
+ gint i;
if (strcmp (name, "static") == 0 || strcmp (name, "transition") == 0) {
Slide *slide = g_new0 (Slide, 1);
@@ -1676,7 +1768,25 @@ handle_start_element (GMarkupParseContex
g_queue_push_tail (parser->slides, slide);
}
-
+ else if (strcmp (name, "size") == 0) {
+ Slide *slide = parser->slides->tail->data;
+ FileSize *size = g_new0 (FileSize, 1);
+ for (i = 0; attr_names[i]; i++) {
+ if (strcmp (attr_names[i], "width") == 0)
+ size->width = atoi (attr_values[i]);
+ else if (strcmp (attr_names[i], "height") == 0)
+ size->height = atoi (attr_values[i]);
+ }
+ if (parser->stack->tail &&
+ (strcmp (parser->stack->tail->data, "file") == 0 ||
+ strcmp (parser->stack->tail->data, "from") == 0)) {
+ slide->file1 = g_slist_prepend (slide->file1, size);
+ }
+ else if (parser->stack->tail &&
+ strcmp (parser->stack->tail->data, "to") == 0) {
+ slide->file2 = g_slist_prepend (slide->file2, size);
+ }
+ }
g_queue_push_tail (parser->stack, g_strdup (name));
}
@@ -1759,6 +1869,8 @@ handle_text (GMarkupParseContext *contex
{
SlideShow *parser = user_data;
Slide *slide = parser->slides->tail? parser->slides->tail->data : NULL;
+ FileSize *fs;
+ gint i;
if (stack_is (parser, "year", "starttime", "background", NULL)) {
parser->start_tm.tm_year = parse_int (text) - 1900;
@@ -1785,12 +1897,47 @@ handle_text (GMarkupParseContext *contex
}
else if (stack_is (parser, "file", "static", "background", NULL) ||
stack_is (parser, "from", "transition", "background", NULL)) {
- slide->file1 = g_strdup (text);
- slide->file1 = make_uri (slide->file1);
+ for (i = 0; text[i]; i++) {
+ if (!g_ascii_isspace (text[i]))
+ break;
+ }
+ if (text[i] == 0)
+ return;
+ fs = g_new (FileSize, 1);
+ fs->width = -1;
+ fs->height = -1;
+ fs->file = make_uri (g_strdup (text));
+ slide->file1 = g_slist_prepend (slide->file1, fs);
+ if (slide->file1->next != NULL)
+ parser->changes_with_size = 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 = make_uri (g_strdup (text));
+ if (slide->file1->next != NULL)
+ parser->changes_with_size = TRUE;
}
else if (stack_is (parser, "to", "transition", "background", NULL)) {
- slide->file2 = g_strdup (text);
- slide->file2 = make_uri (slide->file2);
+ for (i = 0; text[i]; i++) {
+ if (!g_ascii_isspace (text[i]))
+ break;
+ }
+ if (text[i] == 0)
+ return;
+ fs = g_new (FileSize, 1);
+ fs->width = -1;
+ fs->height = -1;
+ fs->file = make_uri (g_strdup (text));
+ slide->file2 = g_slist_prepend (slide->file2, fs);
+ if (slide->file2->next != NULL)
+ parser->changes_with_size = TRUE;
+ }
+ else if (stack_is (parser, "size", "to", "transition", "background", NULL)) {
+ fs = slide->file2->data;
+ fs->file = make_uri (g_strdup (text));
+ if (slide->file2->next != NULL)
+ parser->changes_with_size = TRUE;
}
}
@@ -1798,12 +1945,25 @@ static void
slideshow_free (SlideShow *show)
{
GList *list;
+ GSList *slist;
+ FileSize *size;
for (list = show->slides->head; list != NULL; list = list->next) {
Slide *slide = list->data;
-
- g_free (slide->file1);
- g_free (slide->file2);
+ for (slist = slide->file1; slist != NULL; slist = slist->next) {
+ size = slist->data;
+ g_free (size->file);
+ g_free (size);
+ }
+ g_slist_free (slide->file1);
+
+ for (slist = slide->file2; slist != NULL; slist = slist->next) {
+ size = slist->data;
+ g_free (size->file);
+ g_free (size);
+ }
+ g_slist_free (slide->file2);
+
g_free (slide);
}
@@ -1825,15 +1985,26 @@ dump_bg (SlideShow *show)
{
#if 0
GList *list;
+ GSList *slist;
for (list = show->slides->head; list != NULL; list = list->next)
{
Slide *slide = list->data;
g_print ("\nSlide: %s\n", slide->fixed? "fixed" : "transition");
- g_print ("duration: %d\n", slide->duration);
- g_print ("file1: %p %s\n", slide, slide->file1);
- g_print ("file2: %s\n", slide->file2);
+ g_print ("duration: %f\n", slide->duration);
+ g_print ("File1:\n");
+ for (slist = slide->file1; slist != NULL; slist = slist->next) {
+ FileSize *size = slist->data;
+ g_print ("\t%s (%dx%d)\n",
+ size->file, size->width, size->height);
+ }
+ g_print ("File2:\n");
+ for (slist = slide->file2; slist != NULL; slist = slist->next) {
+ FileSize *size = slist->data;
+ g_print ("\t%s (%dx%d)\n",
+ size->file, size->width, size->height);
+ }
}
#endif
}
@@ -1896,8 +2067,8 @@ read_slideshow_file (const char *uri,
show = NULL;
}
- if (!g_markup_parse_context_end_parse (context, err)) {
- if (show) {
+ if (show) {
+ if (!g_markup_parse_context_end_parse (context, err)) {
slideshow_free (show);
show = NULL;
}
@@ -1988,3 +2159,10 @@ get_thumb_annotations (GdkPixbuf *thumb,
return FALSE;
}
+
+static gboolean
+slideshow_changes_with_size (SlideShow *show)
+{
+ return show->changes_with_size;
+}
+