eel-background cleanup



Hi,

The attached patch gets rid of EelCanvasBuf and the libart dependency,
and reimplements with pixbuf operations instead. It also deletes
various pointless caches and deletes some dead code. The net win is
438 lines of code.

Soren

Index: eel/eel-background.c
===================================================================
--- eel/eel-background.c	(revision 1848)
+++ eel/eel-background.c	(working copy)
@@ -37,7 +37,6 @@
 #include <gtk/gtkprivate.h>
 #include <gtk/gtkselection.h>
 #include <gtk/gtksignal.h>
-#include <libart_lgpl/art_rgb.h>
 #include <eel/eel-canvas.h>
 #include <eel/eel-canvas-util.h>
 #include <libgnomevfs/gnome-vfs-async-ops.h>
@@ -50,57 +49,32 @@
 #include <X11/Xatom.h>
 #include <gdk/gdkx.h>
 
+static void       eel_background_class_init                (gpointer       klass);
+static void       eel_background_init                      (gpointer       object,
+							    gpointer       klass);
+static void       eel_background_finalize                  (GObject       *object);
+static void       eel_background_start_loading_image       (EelBackground *background,
+							    gboolean       emit_appearance_change,
+							    gboolean       load_async);
+static gboolean   eel_background_is_image_load_in_progress (EelBackground *background);
+static gboolean   eel_background_swap_timeout              (gpointer       data);
+static void       eel_background_cancel_swap               (EelBackground *background);
+static void       eel_background_start_swap                (EelBackground *background);
+static void       eel_background_ensure_image_nonswapped   (EelBackground *background);
+static GdkPixmap *eel_background_get_pixmap_and_color      (EelBackground *background,
+							    GdkWindow     *window,
+							    GdkColor      *color,
+							    gboolean      *changes_with_size);
+static void       eel_background_draw                      (EelBackground *background,
+							    GdkDrawable   *drawable,
+							    int	           entire_width,
+							    int            entire_height);
 
-/* FIXME: This could really be eliminated now */
-typedef struct {
-	/* 24-bit RGB buffer for rendering */
-	guchar *buf;
-
-	/* Rectangle describing the rendering area */
-	ArtIRect rect;
-
-	/* Rowstride for the buffer */
-	int buf_rowstride;
-
-	/* Background color, given as 0xrrggbb */
-	guint32 bg_color;
-
-	/* Invariant: at least one of the following flags is true. */
-
-	/* Set when the render rectangle area is the solid color bg_color */
-	unsigned int is_bg : 1;
-
-	/* Set when the render rectangle area is represented by the buf */
-	unsigned int is_buf : 1;
-} EelCanvasBuf;
-
-static void     eel_background_class_init                (gpointer       klass);
-static void     eel_background_init                      (gpointer       object,
-							  gpointer       klass);
-static void     eel_background_finalize                  (GObject       *object);
-static void     eel_background_start_loading_image       (EelBackground *background,
-							  gboolean       emit_appearance_change,
-							  gboolean       load_async);
-static gboolean eel_background_is_image_load_in_progress (EelBackground *background);
-static void     eel_background_draw_to_canvas            (EelBackground *background,
-							  EelCanvasBuf  *buffer,
-							  int            entire_width,
-							  int            entire_height);
-static void     eel_background_draw_aa                   (EelBackground *background,
-							  EelCanvasBuf  *buffer);
-					  
-static gboolean eel_background_swap_timeout              (gpointer data);
-static void     eel_background_cancel_swap               (EelBackground *background);
-static void     eel_background_start_swap                (EelBackground *background);
-static void     eel_background_ensure_image_nonswapped   (EelBackground *background);
-
-
 EEL_CLASS_BOILERPLATE (EelBackground, eel_background, GTK_TYPE_OBJECT)
 
 enum {
 	APPEARANCE_CHANGED,
 	SETTINGS_CHANGED,
-	DETERMINE_IMAGE_PLACEMENT,
 	IMAGE_LOADING_DONE,
 	RESET,
 	LAST_SIGNAL
@@ -116,15 +90,6 @@
 struct EelBackgroundDetails {
 	char *color;
 	
-	int gradient_num_pixels;
-	guchar *gradient_buffer;
-	gboolean gradient_is_horizontal;
-
-	gboolean is_solid_color;
-	GdkColor solid_color;
-
-	gboolean constant_size;
-	
 	char *image_uri;
 	time_t image_mtime;
 	GdkPixbuf *image;
@@ -192,16 +157,6 @@
 			      g_cclosure_marshal_VOID__INT,
 			      G_TYPE_NONE,
 			      1, G_TYPE_INT);
-	signals[DETERMINE_IMAGE_PLACEMENT] = 
-		g_signal_new ("determine_image_placement",
-			      G_TYPE_FROM_CLASS (object_class),
-			      G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
-			      G_STRUCT_OFFSET (EelBackgroundClass,
-					       determine_image_placement),
-			      NULL, NULL,
-			      eel_marshal_ENUM__INT_INT,
-			      EEL_TYPE_BACKGROUND_IMAGE_PLACEMENT,
-			      2, G_TYPE_INT, G_TYPE_INT);
 	signals[IMAGE_LOADING_DONE] =
 		g_signal_new ("image_loading_done",
 			      G_TYPE_FROM_CLASS (object_class),
@@ -235,8 +190,6 @@
 	background = EEL_BACKGROUND (object);
 
 	background->details = g_new0 (EelBackgroundDetails, 1);
-	background->details->constant_size = FALSE;
-	background->details->is_solid_color = TRUE;
 }
 
 /* The safe way to clear an image from a background is:
@@ -265,7 +218,6 @@
 	background->details->load_image_handle = NULL;
 
 	g_free (background->details->color);
-	g_free (background->details->gradient_buffer);
 	g_free (background->details->image_uri);
 	eel_background_remove_current_image (background);
 
@@ -283,9 +235,7 @@
 eel_background_set_is_constant_size (EelBackground *background,
 				     gboolean       constant_size)
 {
-	g_return_if_fail (EEL_IS_BACKGROUND (background));
-	
-	background->details->constant_size = constant_size;
+	/* FIXME: nautilus calls this function; that call should just be deleted */
 }
 
 EelBackgroundImagePlacement
@@ -336,62 +286,61 @@
 {
 	return EEL_BACKGROUND (g_object_new (EEL_TYPE_BACKGROUND, NULL));
 }
- 
-static void
-reset_cached_color_info (EelBackground *background)
+
+static gboolean
+is_solid_color (const EelBackground *background)
 {
-	background->details->gradient_num_pixels = 0;
-	
-	background->details->is_solid_color = !eel_gradient_is_gradient (background->details->color);
-	
-	if (background->details->is_solid_color) {
-		g_free (background->details->gradient_buffer);
-		background->details->gradient_buffer = NULL;
-		eel_gdk_color_parse_with_white_default (background->details->color, &background->details->solid_color);
-	} else {
-		/* If color is still a gradient, don't g_free the buffer, eel_background_ensure_gradient_buffered
-		 * uses g_realloc to try to reuse it.
-		 */
-		background->details->gradient_is_horizontal = eel_gradient_is_horizontal (background->details->color);
-	}
+	return !eel_gradient_is_gradient (background->details->color);
 }
 
+static gboolean
+is_horizontal (const EelBackground *background)
+{
+	return eel_gradient_is_horizontal (background->details->color);
+}
+
 static void
-eel_background_ensure_gradient_buffered (EelBackground *background, int dest_width, int dest_height)
+fill_run (guchar *buf, guchar r, guchar g, guchar b, gint n)
 {
-	int num_pixels;
+  int i;
 
+  if (r == g && g == b)
+    {
+      memset (buf, g, n + n + n);
+    }
+  else
+    {
+      for (i = 0; i < n; i++)
+        {
+          *buf++ = r;
+          *buf++ = g;
+          *buf++ = b;
+        }
+    }
+}
+
+static char *
+create_gradient (const char *spec,
+		 int	     n_pixels)
+{
 	guchar *buff_ptr;
 	guchar *buff_limit;
 
 	GdkColor cur_color;
 
 	char* color_spec;
-	const char* spec_ptr;
+	guchar *result;
 
-	if (background->details->is_solid_color) {
-		return;
-	}
-
-	num_pixels = background->details->gradient_is_horizontal ? dest_width : dest_height;
-
-	if (background->details->gradient_num_pixels == num_pixels) {
-		return;
-	}
-
-	background->details->gradient_num_pixels = num_pixels;
-	background->details->gradient_buffer = g_realloc (background->details->gradient_buffer, num_pixels * 3);
+	result = g_malloc (n_pixels * 3);
 	
-	buff_ptr   = background->details->gradient_buffer;
-	buff_limit = background->details->gradient_buffer + num_pixels * 3;
+	buff_ptr   = result;
+	buff_limit = result + n_pixels * 3;
 
-	spec_ptr = background->details->color;
-	
-	color_spec = eel_gradient_parse_one_color_spec (spec_ptr, NULL, &spec_ptr);
+	color_spec = eel_gradient_parse_one_color_spec (spec, NULL, &spec);
 	eel_gdk_color_parse_with_white_default (color_spec, &cur_color);
 	g_free (color_spec);
 
-	while (spec_ptr != NULL && buff_ptr < buff_limit) {
+	while (spec != NULL && buff_ptr < buff_limit) {
 		int percent;
 		int fill_pos;
 		int fill_width;
@@ -399,7 +348,7 @@
 		guchar *fill_limit;
 		GdkColor new_color;
 	
-		color_spec = eel_gradient_parse_one_color_spec (spec_ptr, &percent, &spec_ptr);
+		color_spec = eel_gradient_parse_one_color_spec (spec, &percent, &spec);
 		eel_gdk_color_parse_with_white_default (color_spec, &new_color);
 		g_free (color_spec);
 
@@ -408,7 +357,7 @@
 		db = new_color.blue  - cur_color.blue;
 
 		fill_pos   = 1;
-		fill_limit = MIN (background->details->gradient_buffer + 3 * ((num_pixels * percent) / 100), buff_limit);
+		fill_limit = MIN (result + 3 * ((n_pixels * percent) / 100), buff_limit);
 		fill_width = (fill_limit - buff_ptr) / 3;
 		
 		while (buff_ptr < fill_limit) {
@@ -421,128 +370,46 @@
 	}
 
 	/* fill in the remainder */
-	art_rgb_fill_run (buff_ptr, cur_color.red, cur_color.green, cur_color.blue, (buff_limit - buff_ptr) / 3);	
-}
+	fill_run (buff_ptr, cur_color.red, cur_color.green, cur_color.blue, (buff_limit - buff_ptr) / 3);
 
-static void
-canvas_gradient_helper_v (const EelCanvasBuf *buf, const art_u8 *gradient_buff)
-{
-	int width  = buf->rect.x1 - buf->rect.x0;
-	int height = buf->rect.y1 - buf->rect.y0;
+	return result;
+}	
 
-	art_u8 *dst       = buf->buf;
-	art_u8 *dst_limit = buf->buf + height * buf->buf_rowstride;
-
-	gradient_buff += buf->rect.y0 * 3;
-	
-	while (dst < dst_limit) {
-		art_u8 r = *gradient_buff++;
-		art_u8 g = *gradient_buff++;
-		art_u8 b = *gradient_buff++;
- 		art_rgb_fill_run (dst, r, g, b, width);
-		dst += buf->buf_rowstride;
-	}
-}
-
 static void
-canvas_gradient_helper_h (const EelCanvasBuf *buf, const art_u8 *gradient_buff)
+draw_gradient (const EelBackground *background,
+	       const GdkPixbuf *pixbuf)
+	       	       
 {
-	int width  = buf->rect.x1 - buf->rect.x0;
-	int height = buf->rect.y1 - buf->rect.y0;
-
-	art_u8 *dst       = buf->buf;
-	art_u8 *dst_limit = buf->buf + height * buf->buf_rowstride;
-
-	int copy_bytes_per_row = width * 3;
-
-	gradient_buff += buf->rect.x0 * 3;
+	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;
 	
-	while (dst < dst_limit) {
- 		memcpy (dst, gradient_buff, copy_bytes_per_row);
-		dst += buf->buf_rowstride;
-	}
-}
-
-static void
-fill_rgb (EelCanvasBuf *buf, art_u8 r, art_u8 g, art_u8 b)
-{
-	art_u8 *dst = buf->buf;
-	int width = buf->rect.x1 - buf->rect.x0;
-	int height = buf->rect.y1 - buf->rect.y0;
-
-	if (buf->buf_rowstride == width * 3) {
-	 	art_rgb_fill_run (dst, r, g, b, width * height);
-	} else {
-		art_u8 *dst_limit = dst + height * buf->buf_rowstride;
+	if (is_horizontal (background)) {
+		guchar *gradient = create_gradient (background->details->color, width);
+		int copy_bytes_per_row = width * 3;
+		
 		while (dst < dst_limit) {
-	 		art_rgb_fill_run (dst, r, g, b, width);
-			dst += buf->buf_rowstride;
+			memcpy (dst, gradient, copy_bytes_per_row);
+			dst += rowstride;
 		}
-	}
-}
+		g_free (gradient);
+	} else {
+		guchar *gb, *gradient;
 
-
-static void
-fill_canvas_from_gradient_buffer (const EelCanvasBuf *buf, const EelBackground *background)
-{
-	g_return_if_fail (background->details->gradient_buffer != NULL);
-
-	/* FIXME bugzilla.eazel.com 4876: This hack is needed till we fix background
-	 * scolling.
-	 *
-	 * I.e. currently you can scroll off the end of the gradient - and we
-	 * handle this by pegging it the the last rgb value.
-	 *
-	 * It might be needed permanently after depending on how this is fixed.
-	 * If we tie gradients to the boundry of icon placement (as opposed to
-	 * window size) then when dragging an icon you might scroll off the
-	 * end of the gradient - which will get recaluated after the drop.
-	 */
-	if (background->details->gradient_is_horizontal) {
-		if (buf->rect.x1 > background->details->gradient_num_pixels) {
-			art_u8 *rgb888 = background->details->gradient_buffer + (background->details->gradient_num_pixels - 1) * 3;
-			EelCanvasBuf gradient = *buf;
-			EelCanvasBuf overflow = *buf;
-			gradient.rect.x1 =  gradient.rect.x0 < background->details->gradient_num_pixels ? background->details->gradient_num_pixels : gradient.rect.x0;
-			overflow.buf += (gradient.rect.x1 - gradient.rect.x0) * 3;
-			overflow.rect.x0 = gradient.rect.x1;
-			fill_rgb (&overflow, rgb888[0], rgb888[1], rgb888[2]);
-			canvas_gradient_helper_h (&gradient, background->details->gradient_buffer);
-			return;
+		gb = gradient = create_gradient (background->details->color, height);
+		while (dst < dst_limit) {
+			guchar r = *gb++;
+			guchar g = *gb++;
+			guchar b = *gb++;
+			fill_run (dst, r, g, b, width);
+			dst += rowstride;
 		}
-	} else {
-		if (buf->rect.y1 > background->details->gradient_num_pixels) {
-			art_u8 *rgb888 = background->details->gradient_buffer + (background->details->gradient_num_pixels - 1) * 3;
-			EelCanvasBuf gradient = *buf;
-			EelCanvasBuf overflow = *buf;
-			gradient.rect.y1 = gradient.rect.y0 < background->details->gradient_num_pixels ? background->details->gradient_num_pixels : gradient.rect.y0;
-			overflow.buf += (gradient.rect.y1 - gradient.rect.y0) * gradient.buf_rowstride;
-			overflow.rect.y0 = gradient.rect.y1;
-			fill_rgb (&overflow, rgb888[0], rgb888[1], rgb888[2]);
-			canvas_gradient_helper_v (&gradient, background->details->gradient_buffer);
-			return;
-		}
+		g_free (gradient);
 	}
-
-	(background->details->gradient_is_horizontal ? canvas_gradient_helper_h : canvas_gradient_helper_v) (buf, background->details->gradient_buffer);
 }
 
-/* Initializes a pseudo-canvas buf so canvas drawing routines can be used to draw into a pixbuf.
- */
-static void
-canvas_buf_from_pixbuf (EelCanvasBuf* buf, GdkPixbuf *pixbuf, int x, int y, int width, int height)
-{
-	buf->buf =  gdk_pixbuf_get_pixels (pixbuf);
-	buf->buf_rowstride =  gdk_pixbuf_get_rowstride (pixbuf);
-	buf->rect.x0 = x;
-	buf->rect.y0 = y;
-	buf->rect.x1 = x + width;
-	buf->rect.y1 = y + height;
-	buf->bg_color = 0xFFFFFFFF;
-	buf->is_bg = TRUE;
-	buf->is_buf = FALSE;
-}
-
 static gboolean
 eel_background_image_totally_obscures (EelBackground *background)
 {
@@ -583,37 +450,37 @@
 static void
 eel_background_cancel_swap (EelBackground *background)
 {
-    if (background->details->swap_timeout > 0) {
-    	    g_source_remove (background->details->swap_timeout);
-	    background->details->swap_timeout = 0;
-    }
+	if (background->details->swap_timeout > 0) {
+		g_source_remove (background->details->swap_timeout);
+		background->details->swap_timeout = 0;
+	}
 }
 
 static void
 eel_background_start_swap (EelBackground *background)
 {
-    if (!background->details->is_desktop) {
-            return;
-    }
-    if (background->details->image_uri == NULL || background->details->image == NULL) {
-	    return;
-    }
-    if (background->details->swap_timeout > 0) {
-	    g_source_remove (background->details->swap_timeout);
-    }
-    background->details->swap_timeout = g_timeout_add (30000, eel_background_swap_timeout, background);	
+	if (!background->details->is_desktop) {
+		return;
+	}
+	if (background->details->image_uri == NULL || background->details->image == NULL) {
+		return;
+	}
+	if (background->details->swap_timeout > 0) {
+		g_source_remove (background->details->swap_timeout);
+	}
+	background->details->swap_timeout = g_timeout_add (30000, eel_background_swap_timeout, background);	
 }
 
 static void
 eel_background_ensure_image_nonswapped (EelBackground *background)
 {
-    if (!background->details->is_desktop) {
-    	    return;
-    }
-    if (background->details->image_uri != NULL && background->details->image == NULL) {
-	    eel_background_start_loading_image (background, FALSE, FALSE);
-    }	
-    eel_background_start_swap (background);
+	if (!background->details->is_desktop) {
+		return;
+	}
+	if (background->details->image_uri != NULL && background->details->image == NULL) {
+		eel_background_start_loading_image (background, FALSE, FALSE);
+	}	
+	eel_background_start_swap (background);
 }
 
 static void
@@ -731,10 +598,10 @@
 {
 	*pixmap_width = 0;	
 	*pixmap_height = 0;
-	*changes_with_size = ! background->details->constant_size;
+	*changes_with_size = ! background->details->is_desktop;
 	
 	if (background->details->image == NULL) {
-		if (background->details->is_solid_color) {
+		if (is_solid_color (background)) {
 			if (!background->details->is_desktop) {
 	    	    		*changes_with_size = FALSE;
 				return FALSE;
@@ -750,7 +617,7 @@
 				return TRUE;
 			}
 		}
-		if (background->details->gradient_is_horizontal) {
+		if (is_horizontal (background)) {
 			*pixmap_width = entire_width;
 			*pixmap_height = GRADIENT_PIXMAP_TILE_SIZE;
 		} else {
@@ -761,12 +628,12 @@
 	} else if (!eel_background_is_image_load_in_progress (background)) {
 		switch (background->details->image_placement) {
 		case EEL_BACKGROUND_TILED:
-			if (background->details->is_solid_color || !gdk_pixbuf_get_has_alpha (background->details->image)) {
+			if (is_solid_color (background) || !gdk_pixbuf_get_has_alpha (background->details->image)) {
 				*pixmap_width = background->details->image_width_unscaled;
 				*pixmap_height = background->details->image_height_unscaled;
 				*changes_with_size = FALSE;
 			} else {
-				if (background->details->gradient_is_horizontal) {
+				if (is_horizontal (background)) {
 					*pixmap_width = entire_width;
 					*pixmap_height = background->details->image_height_unscaled;
 				} else {
@@ -787,19 +654,6 @@
 	return FALSE;
 }
 
-gboolean
-eel_background_get_suggested_pixmap_size (EelBackground    *background,
-					  int               entire_width,
-					  int               entire_height,
-					  int              *pixmap_width,
-					  int              *pixmap_height)
-{
-	gboolean changes_with_size;
-
-	return get_pixmap_size (background, entire_width, entire_height,
-                         pixmap_width, pixmap_height, &changes_with_size);
-}
-
 static void
 eel_background_unrealize (EelBackground *background)
 {
@@ -919,28 +773,50 @@
 	XFlush (display);
 }
 
+static void
+drawable_get_adjusted_size (EelBackground *background,
+			    GdkDrawable   *drawable,
+			    int		  *width,
+			    int	          *height)
+{
+	GdkScreen *screen;
+	
+	/* 
+	 * Screen resolution change makes root drawable have incorrect size.
+	 */    
+	gdk_drawable_get_size (drawable, width, height);
+
+	if (background->details->is_desktop) {
+		screen = gdk_drawable_get_screen (drawable);
+		*width = gdk_screen_get_width (screen);
+		*height = gdk_screen_get_height (screen);
+	}
+}
+
 static gboolean
-eel_background_ensure_realized (EelBackground *background, GdkWindow *window,
-				int entire_width, int entire_height)
+eel_background_ensure_realized (EelBackground *background, GdkWindow *window)
 {
 	GdkColor color;
 	int pixmap_width, pixmap_height;
 	char *start_color_spec;
  	GdkPixmap *pixmap;
-	GdkGC *gc;
 	GtkWidget *widget;
 	GtkStyle *style;
 	gboolean changed;
+	int entire_width;
+	int entire_height;
 
+	drawable_get_adjusted_size (background, window, &entire_width, &entire_height);
+
 	/* Try to parse the color spec.  If we fail, default to the style's color */
 
         eel_background_ensure_image_nonswapped (background);
 
 	start_color_spec = eel_gradient_get_start_color_spec (background->details->color);
 
-	if (start_color_spec && eel_gdk_color_parse (start_color_spec, &color))
+	if (start_color_spec && eel_gdk_color_parse (start_color_spec, &color)) {
 		background->details->background_color = color;
-	else {
+	} else {
 		/* Get the widget to which the window belongs and its style as well */
 		gdk_window_get_user_data (window, (void **) &widget);
 		if (widget != NULL) {
@@ -984,12 +860,7 @@
 			pixmap = gdk_pixmap_new (window, pixmap_width, pixmap_height, -1);
                 }
 		
-		gc = gdk_gc_new (pixmap);
-		eel_background_pre_draw (background,  entire_width, entire_height);
-		eel_background_draw (background, pixmap, gc,
-				     0, 0, 0, 0,
-				     pixmap_width, pixmap_height);
-		g_object_unref (gc);
+		eel_background_draw (background, pixmap, entire_width, entire_height);
 		background->details->background_pixmap = pixmap;
 		changed = TRUE;
 	}
@@ -1002,15 +873,18 @@
 	return changed;
 }
 
-GdkPixmap *
+static GdkPixmap *
 eel_background_get_pixmap_and_color (EelBackground *background,
 				     GdkWindow     *window,
-				     int            entire_width,
-				     int            entire_height,
 				     GdkColor      *color,
 				     gboolean      *changes_with_size)
 {
-	eel_background_ensure_realized (background, window, entire_width, entire_height);
+	int entire_width;
+	int entire_height;
+
+	drawable_get_adjusted_size (background, window, &entire_width, &entire_height);
+
+	eel_background_ensure_realized (background, window);
 	
 	*color = background->details->background_color;
 	*changes_with_size = background->details->background_changes_with_size;
@@ -1042,12 +916,10 @@
 	
 	background = eel_get_widget_background (widget);
 
-	gdk_drawable_get_size (widget->window, &window_width, &window_height);
+	drawable_get_adjusted_size (background, widget->window, &window_width, &window_height);
 	
 	pixmap = eel_background_get_pixmap_and_color (background,
 						      widget->window,
-						      window_width,
-						      window_height,
 						      &color,
 						      &changes_with_size);
 	
@@ -1087,261 +959,81 @@
 	}
 }
 
-void
-eel_background_pre_draw (EelBackground *background, int entire_width, int entire_height)
-{
-	eel_background_ensure_image_scaled (background, entire_width, entire_height);
-	eel_background_ensure_gradient_buffered (background, entire_width, entire_height);
-}
-
-void
-eel_background_draw (EelBackground *background,
-		     GdkDrawable *drawable, GdkGC *gc,
-		     int src_x, int src_y,
-		     int dest_x, int dest_y,
-		     int dest_width, int dest_height)
-{
-	int x, y;
-	int x_canvas, y_canvas;
-	int width, height;
-	
-	EelCanvasBuf buffer;
-	GdkPixbuf *pixbuf;
-
-	/* Non-aa background drawing is done by faking up a EelCanvasBuf
-	 * and passing it to the aa code.
-	 *
-	 * The width and height were chosen to match those used by gnome-canvas
-	 * (IMAGE_WIDTH_AA & IMAGE_HEIGHT_AA in libgnomecanvas/gnome-canvas.c)
-	 * They're not required to match - so this could be changed if necessary.
-	 */
-	static const int PIXBUF_WIDTH = 256;
-	static const int PIXBUF_HEIGHT = 64;
-
-	pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, PIXBUF_WIDTH, PIXBUF_HEIGHT);
-
-	/* x & y are relative to the drawable
-	 */
-	for (y = 0; y < dest_height; y += PIXBUF_HEIGHT) {
-		for (x = 0; x < dest_width; x += PIXBUF_WIDTH) {
-
-			width = MIN (dest_width - x, PIXBUF_WIDTH);
-			height = MIN (dest_height - y, PIXBUF_HEIGHT);
-
-			x_canvas = src_x + x;
-			y_canvas = src_y + y;
-
-			canvas_buf_from_pixbuf (&buffer, pixbuf, x_canvas, y_canvas, width, height);
-			eel_background_draw_aa (background, &buffer);
-			gdk_draw_pixbuf (drawable, gc, pixbuf,
-					 0, 0,
-					 dest_x + x, dest_y + y,
-					 width, height,
-					 GDK_RGB_DITHER_MAX, dest_x + x, dest_y + y);
-		}
-	}
-	
-	g_object_unref (pixbuf);
-}
-
-void
-eel_background_draw_to_drawable (EelBackground *background,
-				 GdkDrawable *drawable, GdkGC *gc,
-				 int drawable_x, int drawable_y,
-				 int drawable_width, int drawable_height,
-				 int entire_width, int entire_height)
-{
-	eel_background_pre_draw (background, entire_width, entire_height);
-	eel_background_draw (background, drawable, gc,
-			     drawable_x, drawable_y,
-			     drawable_x, drawable_y,
-			     drawable_width, drawable_height);
-}
-
-void
-eel_background_draw_to_pixbuf (EelBackground *background,
-			       GdkPixbuf *pixbuf,
-			       int pixbuf_x,
-			       int pixbuf_y,
-			       int pixbuf_width,
-			       int pixbuf_height,
-			       int entire_width,
-			       int entire_height)
-{
-	EelCanvasBuf fake_buffer;
-
-	g_return_if_fail (background != NULL);
-	g_return_if_fail (pixbuf != NULL);
-
-	canvas_buf_from_pixbuf (&fake_buffer, pixbuf, pixbuf_x, pixbuf_y, pixbuf_width, pixbuf_height);
-
-	eel_background_draw_to_canvas (background,
-				       &fake_buffer,
-				       entire_width,
-				       entire_height);
-}
-
 static void
-canvas_draw_pixbuf_helper (art_u8 *dst, int dst_rowstride,
-			   const art_u8 *src, int src_rowstride,
-			   int copy_width, int copy_height)
+pixbuf_copy_area (GdkPixbuf *src,
+		  GdkPixbuf *dest,
+		  int	     src_x,
+		  int	     src_y,
+		  int	     width,
+		  int        height,
+		  int	     dest_x,
+		  int	     dest_y)
 {
-	art_u8 *dst_limit = dst + copy_height * dst_rowstride;
-	int dst_bytes_per_row = copy_width * 3;
-	
-	while (dst < dst_limit) {
- 		memcpy (dst, src, dst_bytes_per_row);
-		dst += dst_rowstride;
-		src += src_rowstride;
-	}
-}
+	int dest_width = gdk_pixbuf_get_width (dest);
+	int dest_height = gdk_pixbuf_get_height (dest);
+	int offset_x = dest_x - src_x;
+	int offset_y = dest_y - src_y;
 
-static void
-canvas_draw_pixbuf_helper_alpha (art_u8 *dst, int dst_rowstride,
-				 const art_u8 *src, int src_rowstride,
-				 int copy_width, int copy_height)
-{
-	art_u8 *dst_limit = dst + copy_height * dst_rowstride;
-	int dst_bytes_per_row = copy_width * 3;
-	
-	while (dst < dst_limit) {
-	
-		art_u8 *dst_p = dst;
-		art_u8 *dst_p_limit = dst + dst_bytes_per_row;
-		
-		const art_u8 *src_p = src;
-		
-		while (dst_p < dst_p_limit) {
-			int alpha = src_p[3];
-			if (alpha) {
-				if (alpha == 255) {
-					dst_p[0] = src_p[0];
-					dst_p[1] = src_p[1];
-					dst_p[2] = src_p[2];
-				} else {
-		  			int tmp;
-					art_u8 bg_r = dst_p[0];
-					art_u8 bg_g = dst_p[1];
-					art_u8 bg_b = dst_p[2];
-
-					tmp = (src_p[0] - bg_r) * alpha;
-					dst_p[0] = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8);
-					tmp = (src_p[1] - bg_g) * alpha;
-					dst_p[1] = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8);
-					tmp = (src_p[2] - bg_b) * alpha;
-					dst_p[2] = bg_b + ((tmp + (tmp >> 8) + 0x80) >> 8);		  
-				}
-			}
-			
-			dst_p += 3;
-			src_p += 4;
-		}
-		
-		dst += dst_rowstride;
-		src += src_rowstride;
+	if (dest_x < 0) {
+		offset_x -= dest_x;
+		dest_x = 0;
 	}
-}
 
-/* Draws a pixbuf into a canvas update buffer (unscaled). The x,y coords are the location
- * of the pixbuf in canvas space (NOT relative to the canvas buffer).
- */
-static void
-canvas_draw_pixbuf (EelCanvasBuf *buf, const GdkPixbuf *pixbuf, int x, int y)
-{
-	art_u8 *dst;
-	int pixbuf_width, pixbuf_height;
-
-	/* copy_left/top/right/bottom define the rect of the pixbuf (pixbuf relative)
-	 * we will copy into the canvas buffer
-	 */
-	int copy_left, copy_top, copy_right, copy_bottom;
-	
-	dst = buf->buf;
-
-	pixbuf_width = gdk_pixbuf_get_width (pixbuf);
-	pixbuf_height = gdk_pixbuf_get_height (pixbuf);
-
-	if (x > buf->rect.x0) {
-		copy_left = 0;
-		dst += (x - buf->rect.x0) * 3;
-	} else {
-		copy_left = buf->rect.x0 - x;
+	if (dest_y < 0) {
+		offset_y -= dest_y;
+		dest_y = 0;
 	}
 	
-	if (x + pixbuf_width > buf->rect.x1) {
-		copy_right = buf->rect.x1 - x;
-	} else {
-		copy_right = pixbuf_width;		
+	if (dest_x + width > dest_width) {
+		width = dest_width - dest_x;
 	}
-	
-	if (copy_left >= copy_right) {
-		return;
-	}
-	
-	if (y > buf->rect.y0) {
-		dst += (y - buf->rect.y0) * buf->buf_rowstride;
-		copy_top = 0;
-	} else {
-		copy_top = buf->rect.y0 - y;
-	}
-	
-	if (y + pixbuf_height > buf->rect.y1) {
-		copy_bottom = buf->rect.y1 - y;
-	} else {
-		copy_bottom = pixbuf_height;		
-	}
 
-	if (copy_top >= copy_bottom) {
-		return;
+	if (dest_y + height > dest_height) {
+		height = dest_height - dest_y;
 	}
-
-	if (gdk_pixbuf_get_has_alpha (pixbuf)) {
-		canvas_draw_pixbuf_helper_alpha (
-			dst,
-			buf->buf_rowstride,
-			gdk_pixbuf_get_pixels (pixbuf) + copy_left * 4 + copy_top * gdk_pixbuf_get_rowstride (pixbuf),
-			gdk_pixbuf_get_rowstride (pixbuf),
-			copy_right - copy_left,
-			copy_bottom - copy_top);
-	} else {
-		canvas_draw_pixbuf_helper (
-			dst,
-			buf->buf_rowstride,
-			gdk_pixbuf_get_pixels (pixbuf) + copy_left * 3 + copy_top * gdk_pixbuf_get_rowstride (pixbuf),
-			gdk_pixbuf_get_rowstride (pixbuf),
-			copy_right - copy_left,
-			copy_bottom - copy_top);
-	}
+	
+	gdk_pixbuf_composite (src, dest,
+			      dest_x, dest_y,
+			      width, height,
+			      offset_x, offset_y,
+			      1, 1, GDK_INTERP_NEAREST,
+			      0xFF);
 }
 
-
 /* fill the canvas buffer with a tiled pixbuf */
 static void
-draw_pixbuf_tiled_aa (GdkPixbuf *pixbuf, EelCanvasBuf *buffer)
+tile_pixbuf (GdkPixbuf *pixbuf, GdkPixbuf *dest)
 {
 	int x, y;
-	int start_x, start_y;
 	int tile_width, tile_height;
+	int dest_width = gdk_pixbuf_get_width (dest);
+	int dest_height = gdk_pixbuf_get_height (dest);
 	
 	tile_width = gdk_pixbuf_get_width (pixbuf);
 	tile_height = gdk_pixbuf_get_height (pixbuf);
-	
-	start_x = buffer->rect.x0 - (buffer->rect.x0 % tile_width);
-	start_y = buffer->rect.y0 - (buffer->rect.y0 % tile_height);
 
-	for (y = start_y; y < buffer->rect.y1; y += tile_height) {
-		for (x = start_x; x < buffer->rect.x1; x += tile_width) {
-			canvas_draw_pixbuf (buffer, pixbuf, x, y);
+	for (y = 0; y < dest_height; y += tile_height) {
+		for (x = 0; x < dest_width; x += tile_width) {
+			pixbuf_copy_area (pixbuf, dest, 0, 0, tile_width, tile_height, x, y);
 		}
 	}
 }
 
-/* draw the background on the anti-aliased canvas */
 static void
-eel_background_draw_aa (EelBackground *background, EelCanvasBuf *buffer)
-{	
-	g_return_if_fail (EEL_IS_BACKGROUND (background));
+eel_background_draw (EelBackground *background,
+		     GdkDrawable *drawable,
+		     int entire_width,
+		     int entire_height)
+{
+	GdkPixbuf *pixbuf;
+	int dest_width, dest_height;
 
+	eel_background_ensure_image_scaled (background, entire_width, entire_height);
+
+	drawable_get_adjusted_size (background, drawable, &dest_width, &dest_height);
+	
+	pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, dest_width, dest_height);
+
 	/* If the image has alpha - we always draw the gradient behind it.
 	 * In principle, we could do better by having already drawn gradient behind
 	 * the scaled image. However, this would add a significant amount of
@@ -1350,25 +1042,29 @@
 	 * This is especially problematic for tiled images with alpha.
 	 */
 	if (!background->details->image ||
-	     gdk_pixbuf_get_has_alpha (background->details->image) ||
-	     buffer->rect.x0  < background->details->image_rect_x ||
-	     buffer->rect.y0  < background->details->image_rect_y ||
-	     buffer->rect.x1  > (background->details->image_rect_x + background->details->image_rect_width) ||
-	     buffer->rect.y1  > (background->details->image_rect_y + background->details->image_rect_height)) {
-		if (background->details->is_solid_color) {
-			fill_rgb (buffer,
-				  background->details->solid_color.red >> 8,
-				  background->details->solid_color.green >> 8,
-				  background->details->solid_color.blue >> 8);
+	    gdk_pixbuf_get_has_alpha (background->details->image) ||
+	    0  < background->details->image_rect_x ||
+	    0  < background->details->image_rect_y ||
+	    dest_width  > (background->details->image_rect_x + background->details->image_rect_width) ||
+	    dest_height  > (background->details->image_rect_y + background->details->image_rect_height)) {
+		if (is_solid_color (background)) {
+			GdkColor color;
+			guint32 pixel;
+			eel_gdk_color_parse_with_white_default (background->details->color, &color);
+			pixel = ((color.red >> 8) << 24)   |
+				((color.green >> 8) << 16) |
+				((color.blue >> 8) << 8)   |
+				0xFF;
+			gdk_pixbuf_fill (pixbuf, pixel);
 		} else {
-			fill_canvas_from_gradient_buffer (buffer, background);
+			draw_gradient (background, pixbuf);
 		}
 	}
-
+	
 	if (background->details->image != NULL) {
 		switch (background->details->image_placement) {
 		case EEL_BACKGROUND_TILED:
-			draw_pixbuf_tiled_aa (background->details->image, buffer);
+			tile_pixbuf (background->details->image, pixbuf);
 			break;
 		default:
 			g_assert_not_reached ();
@@ -1377,31 +1073,25 @@
 		case EEL_BACKGROUND_SCALED:
 		case EEL_BACKGROUND_SCALED_ASPECT:
 		case EEL_BACKGROUND_ZOOM:
-			/* Since the image has already been scaled, all these cases
-			 * can be treated identically.
-			 */
-			canvas_draw_pixbuf (buffer,
-					    background->details->image,
-					    background->details->image_rect_x,
-					    background->details->image_rect_y);
+			/* Image is already scaled, so we can just paint it here */
+			pixbuf_copy_area (background->details->image, pixbuf,
+					  0, 0,
+					  background->details->image_rect_width,
+					  background->details->image_rect_height,
+					  background->details->image_rect_x,
+					  background->details->image_rect_y);
 			break;
 		}
 	}
-					
-	buffer->is_bg  = FALSE;
-	buffer->is_buf = TRUE;
+	
+	gdk_draw_pixbuf (drawable, NULL, pixbuf,
+			 0, 0,
+			 0, 0, dest_width, dest_height,
+			 GDK_RGB_DITHER_MAX, 0, 0);
+	
+	g_object_unref (pixbuf);
 }
 
-static void
-eel_background_draw_to_canvas (EelBackground *background,
-			       EelCanvasBuf *buffer,
-			       int entire_width,
-			       int entire_height)
-{
-	eel_background_pre_draw (background, entire_width, entire_height);
-	eel_background_draw_aa (background, buffer);
-}
-
 char *
 eel_background_get_color (EelBackground *background)
 {
@@ -1429,7 +1119,6 @@
 	}
 	g_free (background->details->color);
 	background->details->color = g_strdup (color);
-	reset_cached_color_info (background);
 
 	return TRUE;
 }
@@ -1469,23 +1158,10 @@
 
 	/* Just ignore errors. */
 	if (pixbuf != NULL) {
-#if 0
-		EelBackgroundImagePlacement style;
-#endif
-
 		g_object_ref (pixbuf);
 		background->details->image = pixbuf;
 		background->details->image_width_unscaled = gdk_pixbuf_get_width (pixbuf);
 		background->details->image_height_unscaled = gdk_pixbuf_get_height (pixbuf);
-
-#if 0
-		style = EEL_BACKGROUND_TILED;
-		g_signal_emit (background, signals[DETERMINE_IMAGE_PLACEMENT], 0,
-			       gdk_pixbuf_get_width (pixbuf),
-			       gdk_pixbuf_get_height (pixbuf),
-			       &style);
-		eel_background_set_image_placement_no_emit (background, style);
-#endif
 	}
 
 	g_signal_emit (background, signals[IMAGE_LOADING_DONE], 0,
@@ -1725,7 +1401,6 @@
 eel_background_set_up_widget (EelBackground *background, GtkWidget *widget)
 {
 	GtkStyle *style;
-	GdkGC *gc;
 	GdkPixmap *pixmap;
 	GdkPixmap *root_pixmap;
 	GdkColor color;
@@ -1736,28 +1411,16 @@
 	int pixmap_height;
 	
 	GdkWindow *window;
-	GdkScreen *screen;
 	gboolean changes_with_size;
 
 	if (!GTK_WIDGET_REALIZED (widget)) {
 		return;
 	}
 
-	gdk_drawable_get_size (widget->window, &window_width, &window_height);
-
-	/* 
-	 * Screen resultion resizing makes root drawable have  incorrect size.
-	 */    
-	if (background->details->is_desktop) {
-		screen = gtk_widget_get_screen (widget);
-		window_width = gdk_screen_get_width (screen);
-		window_height = gdk_screen_get_height (screen);
-	}
-
+	drawable_get_adjusted_size (background, widget->window, &window_width, &window_height);
+	
 	pixmap = eel_background_get_pixmap_and_color (background,
 						      widget->window,
-						      window_width,
-						      window_height,
 						      &color, 
 						      &changes_with_size);
 
@@ -1793,12 +1456,7 @@
 
       				root_pixmap = make_root_pixmap (gdk_drawable_get_screen(window), pixmap_width, pixmap_height);		
 
-				gc = gdk_gc_new (root_pixmap);
-				eel_background_pre_draw (background,  window_width, window_height);
-				eel_background_draw (background, root_pixmap, gc,
-						     0, 0, 0, 0,
-						     pixmap_width, pixmap_height);
-				g_object_unref (gc);
+				eel_background_draw (background, root_pixmap, window_width, window_height);
 			}
 		}	
 		
@@ -1975,30 +1633,6 @@
 	return background;
 }
 
-gboolean
-eel_widget_has_attached_background (GtkWidget *widget)
-{
-	g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
-
-	return g_object_get_data (G_OBJECT (widget), "eel_background") != NULL;
-}
-
-GtkWidget *
-eel_gtk_widget_find_background_ancestor (GtkWidget *widget)
-{
-	g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
-
-	while (widget != NULL) {
-		if (eel_widget_has_attached_background (widget)) {
-			return widget;
-		}
-
-		widget = widget->parent;
-	}
-
-	return NULL;
-}
-
 /* determine if a background is darker or lighter than average, to help clients know what
    colors to draw on top with */
 gboolean
@@ -2012,7 +1646,7 @@
 
 	g_return_val_if_fail (EEL_IS_BACKGROUND (background), FALSE);
 	
-	if (background->details->is_solid_color) {
+	if (is_solid_color (background)) {
 		eel_gdk_color_parse_with_white_default (background->details->color, &color);	
 	} else {
 		start_color_spec = eel_gradient_get_start_color_spec (background->details->color);
Index: eel/eel-background.h
===================================================================
--- eel/eel-background.h	(revision 1848)
+++ eel/eel-background.h	(working copy)
@@ -3,8 +3,7 @@
    eel-background.h: Object for the background of a widget.
 
    Copyright (C) 2000 Eazel, Inc.
-
-   This program is free software; you can redistribute it and/or
+ program is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.
@@ -90,83 +89,31 @@
  * size. This means that EelBackground can use background pixmaps
  * even for backgrounds that otherwise would change when the size
  * chages. The important user is the nautilus desktop window.
+ *
+ * FIXME: This is _only_ used for the desktop background, so fold it into "set_desktop"
  */
 void                        eel_background_set_is_constant_size             (EelBackground               *background,
 									     gboolean                     constant_size);
 
+/* Should be TRUE for desktop background */
+void			    eel_background_set_desktop 			    (EelBackground              *background,
+									     GtkWidget *widget, 
+									     gboolean is_desktop);
+gboolean		    eel_background_is_desktop 			    (EelBackground              *background);
+
 /* Calls to interrogate the current state of a background. */
 char *                      eel_background_get_color                        (EelBackground               *background);
 char *                      eel_background_get_image_uri                    (EelBackground               *background);
 EelBackgroundImagePlacement eel_background_get_image_placement              (EelBackground               *background);
-gboolean                    eel_background_get_suggested_pixmap_size        (EelBackground               *background,
-                                                                             int                          entire_width,
-                                                                             int                          entire_height,
-                                                                             int                         *pixmap_width,
-                                                                             int                         *pixmap_height);
 gboolean                    eel_background_is_dark                          (EelBackground               *background);
 gboolean                    eel_background_is_set                           (EelBackground               *background);
 gboolean                    eel_background_is_loaded                        (EelBackground               *background);
 
 
-GdkPixmap *                 eel_background_get_pixmap_and_color             (EelBackground               *background,
-									     GdkWindow                   *window,
-									     int                          entire_width,
-									     int                          entire_height,
-									     GdkColor                    *color,
-									     gboolean                    *changes_with_size);
-									     
-
 /* Helper function for widgets using EelBackground */
 void                        eel_background_expose                           (GtkWidget                   *widget,
 									     GdkEventExpose              *event);
 
-/* For preping the background to be used in one of the two calls
- * below. Only intended to be called by eel_background_canvas_group_update.
- */
-void                        eel_background_pre_draw                         (EelBackground               *background,
-									     int                          entire_width,
-									     int                          entire_height);
-/* For updating the canvas, non-aa case. Note: eel_background_pre_draw
- * must have been previously called. Only intended to be called by
- * eel_background_canvas_group_draw.
- */
-void                        eel_background_draw                             (EelBackground               *background,
-									     GdkDrawable                 *drawable,
-									     GdkGC                       *gc,
-									     int                          src_x,
-									     int                          src_y,
-									     int                          dest_x,
-									     int                          dest_y,
-									     int                          dest_width,
-									     int                          dest_height);
-
-/* Used to fill a drawable with a background.
- *  - entire_width/height describe the total area the background covers
- *  - drawable_x/y/width/height describe the portion of that area the drawable covers
- */
-void                        eel_background_draw_to_drawable                 (EelBackground               *background,
-									     GdkDrawable                 *drawable,
-									     GdkGC                       *gc,
-									     int                          drawable_x,
-									     int                          drawable_y,
-									     int                          drawable_width,
-									     int                          drawable_height,
-									     int                          entire_width,
-									     int                          entire_height);
-
-/* Used to fill a pixbuf with a background.
- *  - entire_width/height describe the total area the background covers
- *  - drawable_x/y/width/height describe the portion of that area the pixbuf covers
- */
-void                        eel_background_draw_to_pixbuf                   (EelBackground               *background,
-									     GdkPixbuf                   *pixbuf,
-									     int                          pixbuf_x,
-									     int                          pixbuf_y,
-									     int                          pixbuf_width,
-									     int                          pixbuf_height,
-									     int                          entire_width,
-									     int                          entire_height);
-							       
 /* Handles a dragged color being dropped on a widget to change the background color. */
 void                        eel_background_receive_dropped_color            (EelBackground               *background,
 									     GtkWidget                   *widget,
@@ -183,18 +130,6 @@
 /* Gets or creates a background so that it's attached to a widget. */
 EelBackground *             eel_get_widget_background                       (GtkWidget                   *widget);
 
-/* Return whether a background has beed attatched to the given widget. */
-gboolean                    eel_widget_has_attached_background              (GtkWidget                   *widget);
-
-/* Find the background ancestor for the widget. */
-GtkWidget *                 eel_gtk_widget_find_background_ancestor         (GtkWidget                   *widget);
-
-/* Should be TRUE for desktop background */
-void			    eel_background_set_desktop 			    (EelBackground              *background,
-									     GtkWidget *widget, 
-									     gboolean is_desktop);
-gboolean		    eel_background_is_desktop 			    (EelBackground              *background);
-
 typedef struct EelBackgroundDetails EelBackgroundDetails;
 
 struct EelBackground
@@ -218,13 +153,6 @@
 	 */
 	void (* appearance_changed) (EelBackground *);
 
-	/* This signal is emitted when image loading is over to
-	 * allow the placement of the background to be determined
-	 * from the geometry, ie. whether to tile or scale the image.
-	 */
-	EelBackgroundImagePlacement
-             (* determine_image_placement) (EelBackground *, int image_width, int image_height);
- 
 	/* This signal is emitted when image loading is over - whether it
 	 * was successfully loaded or not.
 	 */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]