[gnome-mag/cairo-port: 6/8] Convert cursor drawing to Cairo



commit 548f6aef172920fa22badc9585e34120b3bf0c6e
Author: Benjamin Otte <otte redhat com>
Date:   Fri Aug 13 03:33:45 2010 +0200

    Convert cursor drawing to Cairo
    
    NB: This removes the cursor coloring property. From looking at the code,
    it didn't seem to work anyway.

 magnifier/magnifier-main.c    |    8 +-
 magnifier/magnifier-private.h |    7 +-
 magnifier/magnifier.c         |  329 ++++++++++++++++-------------------------
 magnifier/magnifier.h         |   17 +-
 magnifier/x11/gmag-cursor.c   |   92 +++++-------
 magnifier/x11/gmag-cursor.h   |   12 +-
 magnifier/zoom-region.c       |  123 +++++++---------
 7 files changed, 233 insertions(+), 355 deletions(-)
---
diff --git a/magnifier/magnifier-main.c b/magnifier/magnifier-main.c
index f09e3c7..bc5f2bc 100644
--- a/magnifier/magnifier-main.c
+++ b/magnifier/magnifier-main.c
@@ -42,8 +42,8 @@
 ZoomRegion *zoom_region;
 
 typedef struct {
-	gchar    *target_display;
-	gchar    *source_display;
+	const gchar *target_display;
+	const gchar *source_display;
 	gchar    *cursor_set;
 	gchar    *smoothing_type;
 	gdouble   zoom_factor;
@@ -53,7 +53,6 @@ typedef struct {
 	gint      mouse_poll_time;
 	gint      cursor_size;
 	gdouble   cursor_scale_factor;
-	gint64    cursor_color;
 	gboolean  vertical_split;
 	gboolean  horizontal_split;
 	gboolean  fullscreen;
@@ -90,7 +89,6 @@ static MagnifierOptions global_options = { NULL,      /* target_display */
 					   50,        /* mouse_poll_time */
 					   0,         /* cursor_size */
 					   0.0F,      /* cursor_scale_factor */
-					   0xFF000000,/* cursor_color */
 					   0,         /* vertical_split */
 					   0,         /* horizontal_split */
 					   0,         /* fullscreen */
@@ -122,7 +120,6 @@ static GOptionEntry magnifier_options [] = {
 	{"cursor-set", 0, 0, G_OPTION_ARG_STRING, &global_options.cursor_set, "cursor set to use in target display", NULL},
 	{"cursor-size", 0, 0, G_OPTION_ARG_INT, &global_options.cursor_size, "cursor size to use (overrides cursor-scale-factor)", NULL},
 	{"cursor-scale-factor", 0, 0, G_OPTION_ARG_DOUBLE, &global_options.cursor_scale_factor, "cursor scale factor", NULL},
-	{"cursor-color", 0, 0, G_OPTION_ARG_INT64, &global_options.cursor_color, "cursor color (applied to \'black\' pixels)", NULL},
 	{"vertical", 'v', 0, G_OPTION_ARG_NONE, &global_options.vertical_split, "split screen vertically (if target display = source display)", NULL},
 	{"horizontal", 'h', 0, G_OPTION_ARG_NONE, &global_options.horizontal_split, "split screen horizontally (if target display = source display)", NULL},
 	{"mouse-follow", 'm', 0, G_OPTION_ARG_NONE, &global_options.mouse_follow, "track mouse movements", NULL},
@@ -383,7 +380,6 @@ main (int argc, char** argv)
 		"cursor-size", global_options.cursor_size,
 		"cursor-scale-factor", global_options.cursor_scale_factor != 0.0F ?
 		global_options.cursor_scale_factor : global_options.zoom_factor,
-		"cursor-color", global_options.cursor_color,
 		NULL);
 
   if (!global_options.show_crosswires)
diff --git a/magnifier/magnifier-private.h b/magnifier/magnifier-private.h
index 621beef..86e8f58 100644
--- a/magnifier/magnifier-private.h
+++ b/magnifier/magnifier-private.h
@@ -32,15 +32,10 @@ struct _MagnifierPrivate {
 	GdkWindow   *root;
 	GdkWindow   *overlay;
 	GdkPixmap   *source_drawable;
-	GdkDrawable *cursor;
-        int          cursor_default_size_x;
-        int          cursor_default_size_y;
+	cairo_surface_t *cursor;
 	gboolean     crosswire;
-	GdkBitmap   *cursor_mask;
  	int          cursor_x;
 	int          cursor_y;
-	int          cursor_hotspot_x;
-	int          cursor_hotspot_y;
         gboolean     use_source_cursor;
         GHashTable  *cursorlist;
 	guint        dbus_object_id;
diff --git a/magnifier/magnifier.c b/magnifier/magnifier.c
index efca61e..515a288 100644
--- a/magnifier/magnifier.c
+++ b/magnifier/magnifier.c
@@ -53,7 +53,6 @@ enum {
 	MAGNIFIER_CURSOR_SET_PROP,
 	MAGNIFIER_CURSOR_SIZE_PROP,
 	MAGNIFIER_CURSOR_ZOOM_PROP,
-	MAGNIFIER_CURSOR_HOTSPOT_PROP,
 	MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP,
 	MAGNIFIER_CROSSWIRE_SIZE_PROP,
 	MAGNIFIER_CROSSWIRE_LENGTH_PROP,
@@ -172,90 +171,53 @@ magnifier_zoom_regions_mark_dirty (Magnifier *magnifier, RectBounds rect_bounds)
 }
 
 void
-magnifier_set_cursor_from_pixbuf (Magnifier *magnifier,
-				  GdkPixbuf *cursor_pixbuf)
+magnifier_set_cursor_from_surface (Magnifier *magnifier,
+				   cairo_surface_t *cursor_surface)
 {
-	GdkPixmap *pixmap, *mask;
-	gint width, height;
-	GdkGC *gc;
-	GdkDrawable *drawable = gtk_widget_get_window (GTK_WIDGET (magnifier));
-
 	if (magnifier->priv->cursor) {
-		g_object_unref (magnifier->priv->cursor);
+		cairo_surface_destroy (magnifier->priv->cursor);
 		magnifier->priv->cursor = NULL;
 	}
-	if (drawable && cursor_pixbuf) {
-		const gchar *xhot_string = NULL, *yhot_string = NULL;
-		width = gdk_pixbuf_get_width (cursor_pixbuf);
-		height = gdk_pixbuf_get_height (cursor_pixbuf);
-		pixmap = gdk_pixmap_new (drawable, width, height, -1);
-		gc = gdk_gc_new (pixmap);
-		if (GDK_IS_DRAWABLE (pixmap))
-			gdk_draw_pixbuf (pixmap, gc, cursor_pixbuf, 0, 0, 0, 0,
-					 width, height, GDK_RGB_DITHER_NONE,
-					 0, 0);
-		else
-			DBG (g_warning ("empty cursor pixmap created."));
-		mask = gdk_pixmap_new (drawable, width, height, 1);
-		gdk_pixbuf_render_threshold_alpha (cursor_pixbuf, mask,
-						   0, 0, 0, 0, 
-						   width, height,
-						   200);
-		g_object_unref (gc);
-		magnifier->priv->cursor = pixmap;
-		magnifier->priv->cursor_mask = mask;
-
-		xhot_string = g_object_get_data (G_OBJECT(cursor_pixbuf), "x_hot");
-		yhot_string = g_object_get_data (G_OBJECT(cursor_pixbuf), "y_hot");
-
-		if (xhot_string)
-			magnifier->cursor_hotspot.x = atoi (xhot_string);
-		if (yhot_string)
-			magnifier->cursor_hotspot.y = atoi (yhot_string);
-		if (pixmap) {
-			gdk_drawable_get_size (
-				pixmap,
-				&magnifier->priv->cursor_default_size_x,
-				&magnifier->priv->cursor_default_size_y);
-			magnifier->priv->cursor_hotspot_x =
-				magnifier->cursor_hotspot.x;
-			magnifier->priv->cursor_hotspot_y =
-				magnifier->cursor_hotspot.y;
-		}
+	if (cursor_surface) {
+		magnifier->priv->cursor = cairo_surface_reference (cursor_surface);
 	}
 }
 
 
-GdkPixbuf *
-magnifier_get_pixbuf_for_name (Magnifier *magnifier, const gchar *cursor_name)
+static cairo_surface_t *
+magnifier_get_surface_for_name (Magnifier *magnifier, const gchar *cursor_name)
 {
-    GdkPixbuf *retval = NULL;
+    cairo_surface_t *retval = NULL;
     if (magnifier->priv->cursorlist) 
 	    retval = g_hash_table_lookup (magnifier->priv->cursorlist, cursor_name);
     if (retval) 
-	    g_object_ref (retval);
+	    cairo_surface_reference (retval);
     return retval;
 }
 
 void
-magnifier_set_cursor_pixmap_by_name (Magnifier *magnifier,
-				     const gchar *cursor_name, 
-				     gboolean source_fallback)
+magnifier_set_cursor_by_name (Magnifier *magnifier,
+			      const gchar *cursor_name, 
+			      gboolean source_fallback)
 {
-	GdkPixbuf *pixbuf;
+	cairo_surface_t *surface;
+
 	/* search local table; if not found, use source screen's cursor if source_fallback is TRUE */
-	if ((pixbuf = magnifier_get_pixbuf_for_name (magnifier, cursor_name)) == NULL) {
+        surface = magnifier_get_surface_for_name (magnifier, cursor_name);
+	if (surface == NULL) {
 		if (source_fallback == TRUE)
 		{
-			pixbuf = gmag_cursor_get_source_pixbuf (magnifier);
+			surface = gmag_cursor_get_source_surface (magnifier);
 		}
 		else
 		{
-			pixbuf = magnifier_get_pixbuf_for_name (magnifier, "default");
+			surface = magnifier_get_surface_for_name (magnifier, "default");
 		}
 	}
-	magnifier_set_cursor_from_pixbuf (magnifier, pixbuf);
-	if (pixbuf) g_object_unref (pixbuf);
+
+	magnifier_set_cursor_from_surface (magnifier, surface);
+	if (surface)
+                cairo_surface_destroy (surface);
 }
 
 void
@@ -585,98 +547,6 @@ magnifier_exit (GtkObject *object)
 }
 #endif
 
-void
-magnifier_transform_cursor (Magnifier *magnifier)
-{
-	if (magnifier->priv->cursor) /* don't do this if cursor isn't intialized yet */
-	{
-		int width, height;
-		int size_x, size_y;
-		GdkPixbuf *scaled_cursor_pixbuf;
-		GdkPixbuf *scaled_mask_pixbuf;
-		GdkPixbuf *scaled_mask_pixbuf_alpha;
-		GdkPixbuf *cursor_pixbuf;
-		GdkPixbuf *mask_pixbuf;
-		GdkPixmap *cursor_pixmap = magnifier->priv->cursor;
-		GdkPixmap *mask_pixmap = magnifier->priv->cursor_mask;
-		GdkGC *cgc;
-		GdkGC *mgc;
-
-		if (magnifier->cursor_size_x)
-		{
-			size_x = magnifier->cursor_size_x;
-			size_y = magnifier->cursor_size_y;
-		}
-		else
-		{
-			size_x = magnifier->priv->cursor_default_size_x * 
-			       magnifier->cursor_scale_factor;
-			size_y = magnifier->priv->cursor_default_size_y * 
-			       magnifier->cursor_scale_factor;
-		}
-		gdk_drawable_get_size (magnifier->priv->cursor, &width, &height);
-		if ((size_x == width) && (size_y == height)) {
-			return; /* nothing changes */
-		}
-		cgc = gdk_gc_new (cursor_pixmap);
-		mgc = gdk_gc_new (mask_pixmap);
-		cursor_pixbuf = gdk_pixbuf_get_from_drawable (NULL, cursor_pixmap,
-							      NULL, 0, 0, 0, 0,
-							      width, height);
-		mask_pixbuf = gdk_pixbuf_get_from_drawable (NULL,
-							    mask_pixmap,
-							    NULL, 0, 0, 0, 0,
-							    width, height);
-		scaled_cursor_pixbuf = gdk_pixbuf_scale_simple (
-			cursor_pixbuf, size_x, size_y, GDK_INTERP_NEAREST);
-		
-		magnifier->cursor_hotspot.x = magnifier->priv->cursor_hotspot_x * size_x 
-					    / magnifier->priv->cursor_default_size_x;
-		magnifier->cursor_hotspot.y = magnifier->priv->cursor_hotspot_y * size_y 
-					    / magnifier->priv->cursor_default_size_y;
-					    
-		scaled_mask_pixbuf = gdk_pixbuf_scale_simple (
-			mask_pixbuf, size_x, size_y, GDK_INTERP_NEAREST);
-		g_object_unref (cursor_pixbuf);
-		g_object_unref (mask_pixbuf);
-		g_object_unref (cursor_pixmap);
-		g_object_unref (mask_pixmap);
-		magnifier->priv->cursor = gdk_pixmap_new (
-			gtk_widget_get_window (GTK_WIDGET (magnifier)),
-			size_x, size_y,
-			-1);
-		if (!GDK_IS_DRAWABLE (magnifier->priv->cursor)) 
-		{
-		    DBG (g_warning ("NULL magnifier cursor pixmap."));
-		    return;
-		}
-		magnifier->priv->cursor_mask = gdk_pixmap_new (
-		        gtk_widget_get_window (GTK_WIDGET (magnifier)),
-			size_x, size_y,
-			1);
-		if (GDK_IS_DRAWABLE (magnifier->priv->cursor)) {
-		    gdk_draw_pixbuf (magnifier->priv->cursor,
-				     cgc,
-				     scaled_cursor_pixbuf,
-				     0, 0, 0, 0, size_x, size_y,
-				     GDK_RGB_DITHER_NONE, 0, 0 );
-		}
-		else
-		    DBG (g_warning ("cursor pixmap is non-drawable."));
-		scaled_mask_pixbuf_alpha = gdk_pixbuf_add_alpha (
-			scaled_mask_pixbuf, True, 0, 0, 0);
-		gdk_pixbuf_render_threshold_alpha (scaled_mask_pixbuf_alpha,
-						   magnifier->priv->cursor_mask,
-						   0, 0, 0, 0, size_x, size_y,
-						   0x80);
-		g_object_unref (scaled_mask_pixbuf_alpha);
-		g_object_unref (scaled_cursor_pixbuf);
-		g_object_unref (scaled_mask_pixbuf);
-		g_object_unref (mgc);
-		g_object_unref (cgc);
-	}	
-}
-
 static void
 magnifier_init_cursor_set (Magnifier *magnifier, gchar *cursor_set)
 {
@@ -705,7 +575,8 @@ magnifier_init_cursor_set (Magnifier *magnifier, gchar *cursor_set)
 			g_hash_table_destroy (magnifier->priv->cursorlist);
 		}
 		magnifier->priv->cursorlist = g_hash_table_new_full (g_str_hash, g_str_equal,
-								     g_free, g_object_unref);
+								     g_free, 
+                                                                     (GDestroyNotify) cairo_surface_destroy);
 
 		cursor_dirname = g_strconcat (CURSORSDIR, "/", magnifier->cursor_set, NULL);
 		cursor_dir = g_dir_open (cursor_dirname, 0, NULL);
@@ -719,14 +590,26 @@ magnifier_init_cursor_set (Magnifier *magnifier, gchar *cursor_set)
 				if (pixbuf)
 				{
 					/* add this pixbuf and its name to our list */
+                                        cairo_surface_t *surface;
+                                        cairo_t *cr;
 					gchar **sv, *cname;
+
+                                        surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                                                              gdk_pixbuf_get_width (pixbuf),
+                                                                              gdk_pixbuf_get_height (pixbuf));
+                                        cr = cairo_create (surface);
+                                        gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+                                        cairo_paint (cr);
+                                        cairo_destroy (cr);
+
 					cname = g_path_get_basename (filename);
 					sv = g_strsplit (cname, ".", 2);
 					g_hash_table_insert (magnifier->priv->cursorlist, 
 							     g_strdup (sv[0]),
-							     pixbuf);
+							     surface);
 					g_free (cname);
 					g_strfreev (sv);
+                                        g_object_unref (pixbuf);
 				}
 				g_free (path);
 			}
@@ -735,8 +618,7 @@ magnifier_init_cursor_set (Magnifier *magnifier, gchar *cursor_set)
 		if (cursor_dir) g_dir_close (cursor_dir);
 	}
 	/* don't fallover to source cursor here, we haven't initialized X yet */
-	magnifier_set_cursor_pixmap_by_name (magnifier, "default", FALSE);
-	magnifier_transform_cursor (magnifier);
+	magnifier_set_cursor_by_name (magnifier, "default", FALSE);
 }
 
 static gboolean 
@@ -964,17 +846,11 @@ get_property_cb (GDBusConnection *connection,
 		retval = g_variant_new_array (G_VARIANT_TYPE_INT32, children, 2);
 	} else if (g_strcmp0 (property_name, "CursorZoom") == 0) {
 		retval = g_variant_new_double (magnifier->cursor_scale_factor);
-	} else if (g_strcmp0 (property_name, "CursorHotspot") == 0) {
-		GVariant *children[2];
-
-		children[0] = g_variant_new_int32 (magnifier->cursor_hotspot.x);
-		children[1] = g_variant_new_int32 (magnifier->cursor_hotspot.y);
-		retval = g_variant_new_array (G_VARIANT_TYPE_INT32, children, 2);
 	} else if (g_strcmp0 (property_name, "CursorDefaultSize") == 0) {
 		gint32 csize = 0;
 
 		if (magnifier->priv->cursor) {
-			gdk_drawable_get_size (magnifier->priv->cursor, &csize, &csize);
+			csize = cairo_image_surface_get_width (magnifier->priv->cursor);
 		}
 		retval = g_variant_new_int32 (csize);
 	} else if (g_strcmp0 (property_name, "CrosswireSize") == 0) {
@@ -1042,10 +918,6 @@ set_property_cb (GDBusConnection *connection,
 		g_object_set (magnifier,
 			      "cursor-scale-factor", g_variant_get_double (value),
 			      NULL);
-	} else if (g_strcmp0 (property_name, "CursorColor") == 0) {
-		g_object_set (magnifier,
-			      "cursor-color", g_variant_get_uint32 (value),
-			      NULL);
 	} else if (g_strcmp0 (property_name, "CursorHotspot") == 0) {
 		const int *items;
 		gsize      n_items;
@@ -1205,19 +1077,11 @@ magnifier_gobject_get_property (GObject    *object,
 	case MAGNIFIER_CURSOR_ZOOM_PROP:
 		g_value_set_float (value, magnifier->cursor_scale_factor);
 		break;
-	case MAGNIFIER_CURSOR_HOTSPOT_PROP: {
-		Point *point = g_new (Point, 1);
-
-		*point = magnifier->cursor_hotspot;
-		g_value_set_pointer (value, point);
-	}
-		break;
 	case MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP: {
 		int csize = 0;
 
 		if (magnifier->priv->cursor)
-			gdk_drawable_get_size (magnifier->priv->cursor,
-					       &csize, &csize);
+			csize = cairo_image_surface_get_width (magnifier->priv->cursor);
 		g_value_set_uint (value, csize);
 	}
 		break;
@@ -1421,22 +1285,11 @@ magnifier_gobject_set_property (GObject      *object,
 	case MAGNIFIER_CURSOR_SIZE_PROP:
 		magnifier->cursor_size_x = g_value_get_int (value);
 		magnifier->cursor_size_y = magnifier->cursor_size_x;
-		magnifier_transform_cursor (magnifier);
 		DBG (fprintf (stderr, "Setting cursor size: \t%d\n", magnifier->cursor_size_x));
 		break;
 	case MAGNIFIER_CURSOR_ZOOM_PROP:
 		magnifier->cursor_scale_factor = g_value_get_float (value);
 		DBG (fprintf (stderr, "Setting cursor scale factor: \t%f\n", (float) magnifier->cursor_scale_factor));
-		magnifier_transform_cursor (magnifier);
-		break;
-	case MAGNIFIER_CURSOR_HOTSPOT_PROP: {
-		Point *point = g_value_get_pointer (value);
-
-		magnifier->cursor_hotspot = *point;
-		/* TODO: notify zoomers */
-                /* FIXME: don't call init_cursor, it overwrites this property! */
-		magnifier_transform_cursor (magnifier);
-	}
 		break;
 	case MAGNIFIER_CROSSWIRE_SIZE_PROP:
 		magnifier->crosswire_size = g_value_get_int (value);
@@ -1576,12 +1429,6 @@ magnifier_class_init (MagnifierClass *klass)
 							     0, G_MAXFLOAT, 1.0F,
 							     G_PARAM_READWRITE));
 	g_object_class_install_property (object_class,
-					 MAGNIFIER_CURSOR_HOTSPOT_PROP,
-					 g_param_spec_pointer ("cursor-hotspot",
-							       "CursorHotspot",
-							       "hotspot relative to cursor's upper-left-corner, at default resolition",
-							       G_PARAM_READWRITE));
-	g_object_class_install_property (object_class,
 					 MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP,
 					 g_param_spec_int ("cursor-default-size",
 							   "CursorDefaultSize",
@@ -1717,8 +1564,8 @@ magnifier_new (gboolean     override_redirect,
 	return mag;
 }
 
-GdkDrawable *
-magnifier_get_cursor (Magnifier *magnifier)
+static void
+magnifier_ensure_cursor (Magnifier *magnifier)
 {
         if (magnifier->priv->cursor == NULL) {
 	    if ((fixes_event_base == 0) && 
@@ -1730,18 +1577,96 @@ magnifier_get_cursor (Magnifier *magnifier)
 		pixbuf = gdk_pixbuf_new_from_file (default_cursor_filename, NULL);
 		if (pixbuf) 
 		{
-		    magnifier_set_cursor_from_pixbuf (magnifier, pixbuf);
+                    cairo_surface_t *surface;
+                    cairo_t *cr;
+
+                    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                                          gdk_pixbuf_get_width (pixbuf),
+                                                          gdk_pixbuf_get_height (pixbuf));
+                    cr = cairo_create (surface);
+                    gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+                    cairo_paint (cr);
+                    cairo_destroy (cr);
+
+		    magnifier_set_cursor_from_surface (magnifier, surface);
 		    g_object_unref (pixbuf);
-		    magnifier_transform_cursor (magnifier);
+                    cairo_surface_destroy (surface);
 		}
 		g_free (default_cursor_filename);
 	    } else {
-		GdkPixbuf *cursor_pixbuf = gmag_cursor_get_source_pixbuf (
+		cairo_surface_t *surface = gmag_cursor_get_source_surface (
 			magnifier);
-		magnifier_set_cursor_from_pixbuf (magnifier, cursor_pixbuf);
-		if (cursor_pixbuf) g_object_unref (cursor_pixbuf);
-		magnifier_transform_cursor (magnifier);
+		magnifier_set_cursor_from_surface (magnifier, surface);
+		if (surface) cairo_surface_destroy (surface);
 	    }
         }
-	return magnifier->priv->cursor;
+}
+
+cairo_pattern_t *
+magnifier_get_cursor (Magnifier *magnifier)
+{
+        cairo_matrix_t matrix;
+        cairo_pattern_t *pattern;
+        
+        magnifier_ensure_cursor (magnifier);
+        if (magnifier->priv->cursor == NULL)
+                return NULL;
+
+        pattern = cairo_pattern_create_for_surface (magnifier->priv->cursor);
+        cairo_pattern_set_filter (pattern, CAIRO_FILTER_NEAREST);
+
+        if (magnifier->cursor_size_x)
+        {
+                double xscale, yscale;
+                
+                xscale = (double) cairo_image_surface_get_width (magnifier->priv->cursor) / magnifier->cursor_size_x;
+                yscale = (double) cairo_image_surface_get_height (magnifier->priv->cursor) / magnifier->cursor_size_y;
+
+                cairo_matrix_init_scale (&matrix, xscale, yscale);
+        }
+        else
+        {
+                cairo_matrix_init_scale (&matrix,
+                                         1.0 / magnifier->cursor_scale_factor,
+                                         1.0 / magnifier->cursor_scale_factor);
+        }
+
+        cairo_pattern_set_matrix (pattern, &matrix);
+
+        return pattern;
+}
+
+void
+magnifier_get_cursor_size (Magnifier *    magnifier,
+                           GdkRectangle * rect)
+{
+        double x_hot, y_hot;
+        int width, height;
+
+        magnifier_ensure_cursor (magnifier);
+        if (magnifier->priv->cursor == NULL)
+        {
+                memset (rect, 0, sizeof (GdkRectangle));
+                return;
+        }
+
+        cairo_surface_get_device_offset (magnifier->priv->cursor, &x_hot, &y_hot);
+
+        width = cairo_image_surface_get_width (magnifier->priv->cursor);
+        height = cairo_image_surface_get_height (magnifier->priv->cursor);
+
+        if (magnifier->cursor_size_x)
+        {
+                rect->x = - x_hot * magnifier->cursor_size_x / width;
+                rect->y = - y_hot * magnifier->cursor_size_y / height;
+                rect->width = magnifier->cursor_size_x;
+                rect->height = magnifier->cursor_size_y;
+        }
+        else
+        {
+                rect->x = - x_hot * magnifier->cursor_scale_factor;
+                rect->y = - y_hot * magnifier->cursor_scale_factor;
+                rect->width = magnifier->cursor_scale_factor * width;
+                rect->height = magnifier->cursor_scale_factor * height;
+        }
 }
diff --git a/magnifier/magnifier.h b/magnifier/magnifier.h
index 6885462..cfd640e 100644
--- a/magnifier/magnifier.h
+++ b/magnifier/magnifier.h
@@ -62,7 +62,6 @@ typedef struct {
 	float              cursor_scale_factor;
 	RectBounds         source_bounds;
 	RectBounds         target_bounds;
-	Point	           cursor_hotspot;
 	MagnifierPrivate  *priv;
 } Magnifier;
 
@@ -145,7 +144,10 @@ typedef struct timing {
 
 TimingStruct mag_timing;
 
-GdkDrawable *magnifier_get_cursor    (Magnifier *magnifier);
+cairo_pattern_t * magnifier_get_cursor      (Magnifier *    magnifier);
+void              magnifier_get_cursor_size (Magnifier *    magnifier,
+                                             GdkRectangle * size);
+
 GType        magnifier_get_type      (void) G_GNUC_CONST;
 GdkWindow   *magnifier_get_root      (Magnifier *magnifier);
 Magnifier   *magnifier_new           (gboolean     override_redirect,
@@ -160,12 +162,11 @@ void         magnifier_add_zoom_region (Magnifier  *magnifier,
 					ZoomRegion *zoom_region);
 void         magnifier_notify_damage (Magnifier *magnifier,
 				      GdkRectangle *rect);
-void         magnifier_set_cursor_from_pixbuf (Magnifier *magnifier,
-					       GdkPixbuf *pointer_pixbuf);
-void         magnifier_set_cursor_pixmap_by_name (Magnifier *magnifier,
-						  const gchar *cursor_name, 
-						  gboolean source_fallback);
-void         magnifier_transform_cursor (Magnifier *magnifier);
+void         magnifier_set_cursor_from_surface (Magnifier *magnifier,
+					        cairo_surface_t *surface);
+void         magnifier_set_cursor_by_name (Magnifier *magnifier,
+					   const gchar *cursor_name, 
+					   gboolean source_fallback);
 void         magnifier_zoom_regions_update_pointer (Magnifier *magnifier);
 gboolean     magnifier_full_screen_capable (Magnifier *magnifier);
 
diff --git a/magnifier/x11/gmag-cursor.c b/magnifier/x11/gmag-cursor.c
index 89c1a62..217afbc 100644
--- a/magnifier/x11/gmag-cursor.c
+++ b/magnifier/x11/gmag-cursor.c
@@ -41,50 +41,41 @@ static Window                root_window;
 static gint                  fixes_error_base;
 
 
-static void
-gmag_cursor_cursor_convert_to_rgba (Magnifier *magnifier,
-				    XFixesCursorImage *cursor_image)
-{
-	int i, count = cursor_image->width * cursor_image->height;
-	for (i = 0; i < count; ++i) {
-		guint32 pixval = GUINT_TO_LE (cursor_image->pixels[i]);
-		cursor_image->pixels[i] = pixval;
-	}
-}
-
-static void
-gmag_cursor_free_cursor_pixels (guchar *pixels, gpointer data)
-{
-    XFree (data);
-}
-
-GdkPixbuf *
-gmag_cursor_get_source_pixbuf (Magnifier *magnifier)
+cairo_surface_t *
+gmag_cursor_get_source_surface (Magnifier *magnifier)
 {
 	XFixesCursorImage *cursor_image = XFixesGetCursorImage (dpy);
-        GdkPixbuf *cursor_pixbuf = NULL;
-	gchar *s1, *s2;
+        gulong *cursor_pixels = cursor_image->pixels;
+        cairo_surface_t *surface = NULL;
+        int x, y, stride;
+        guint32 *pixels;
 
 	if (cursor_image) {
-		s1 = (char *) malloc (sizeof (char) * 6);
-		s2 = (char *) malloc (sizeof (char) * 6);
-	        gmag_cursor_cursor_convert_to_rgba (magnifier, cursor_image);
-		cursor_pixbuf = gdk_pixbuf_new_from_data (
-			(guchar *) cursor_image->pixels, GDK_COLORSPACE_RGB,
-			TRUE, 8, cursor_image->width, cursor_image->height,
-			cursor_image->width * 4,
-			gmag_cursor_free_cursor_pixels, cursor_image);
-		g_object_set_data (G_OBJECT (cursor_pixbuf), "x_hot", 
-				   g_ascii_dtostr (
-					   s1, 6,
-					   (gdouble) cursor_image->xhot));
-		g_object_set_data (G_OBJECT (cursor_pixbuf), "y_hot", 
-				   g_ascii_dtostr (
-					   s2, 6,
-					   (gdouble) cursor_image->yhot));
+                surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                                      cursor_image->width,
+                                                      cursor_image->height);
+
+                pixels = (guint32 *) cairo_image_surface_get_data (surface);
+                stride = cairo_image_surface_get_stride (surface);
+                stride /= 4; /* we're using guint32 */
+                for (y = 0; y < cursor_image->height; y++) {
+                        for (x = 0; x < cursor_image->width; x++) {
+                                pixels[x] = *cursor_pixels;
+                                cursor_pixels++;
+                        }
+                        pixels += stride;
+                }
+
+                cairo_surface_mark_dirty (surface);
+
+                /* We offset the surface so 0,0 of the surface ends up being
+                 * at the cursor's hot point */
+                cairo_surface_set_device_offset (surface, 
+                                                 cursor_image->xhot,
+                                                 cursor_image->yhot);
 	}
 
-	return cursor_pixbuf;
+	return surface;
 }
 
 void
@@ -129,35 +120,24 @@ void
 gmag_cursor_events_handler (Magnifier *magnifier, XEvent *ev)
 {
 	XFixesCursorNotifyEvent *cev = (XFixesCursorNotifyEvent *) ev;
-	gchar *s1, *s2;
 
 	if (magnifier->priv->use_source_cursor) {
-			GdkPixbuf *cursor_pixbuf =
-				gmag_cursor_get_source_pixbuf (magnifier);
-			magnifier_set_cursor_from_pixbuf (magnifier,
-							  cursor_pixbuf);
-			s1 = g_object_get_data (G_OBJECT (cursor_pixbuf),
-						  "x_hot");
-			s2 = g_object_get_data (G_OBJECT (cursor_pixbuf),
-						  "y_hot");
-			if (s1) {
-				g_free (s1);
-				g_free (s2);
-			}
-			if (cursor_pixbuf) 
-				g_object_unref (cursor_pixbuf);
+	        cairo_surface_t *surface = gmag_cursor_get_source_surface (magnifier);
+		
+                magnifier_set_cursor_from_surface (magnifier, surface);
+		if (surface) 
+			cairo_surface_destroy (surface);
 	} else {
 		if (cev)
-			magnifier_set_cursor_pixmap_by_name (
+			magnifier_set_cursor_by_name (
 				magnifier,
 				gdk_x11_get_xatom_name (cev->cursor_name),
 				TRUE);
 		else
-			magnifier_set_cursor_pixmap_by_name (
+			magnifier_set_cursor_by_name (
 				magnifier, "default", TRUE);
 	}
 	
-	magnifier_transform_cursor (magnifier);
 	magnifier_zoom_regions_update_pointer (magnifier);
 #ifdef CURSOR_DEBUG
 	if (cev)
diff --git a/magnifier/x11/gmag-cursor.h b/magnifier/x11/gmag-cursor.h
index b50e935..6dd9a96 100644
--- a/magnifier/x11/gmag-cursor.h
+++ b/magnifier/x11/gmag-cursor.h
@@ -28,12 +28,12 @@
 
 #include <X11/Xlib.h>
 
-#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <cairo.h>
 
-gint       gmag_cursor_init (Magnifier *magnifier, Display *dpy_conn);
-GdkPixbuf *gmag_cursor_get_source_pixbuf (Magnifier *magnifier);
-void       gmag_cursor_events_handler (Magnifier *magnifier, XEvent *ev);
-void       gmag_cursor_hide (Magnifier *magnifier);
-void       gmag_cursor_show (Magnifier *magnifier);
+gint             gmag_cursor_init (Magnifier *magnifier, Display *dpy_conn);
+cairo_surface_t *gmag_cursor_get_source_surface (Magnifier *magnifier);
+void             gmag_cursor_events_handler (Magnifier *magnifier, XEvent *ev);
+void             gmag_cursor_hide (Magnifier *magnifier);
+void             gmag_cursor_show (Magnifier *magnifier);
 
 #endif /* GMAG_CURSOR_H_ */
diff --git a/magnifier/zoom-region.c b/magnifier/zoom-region.c
index ea28a0b..5a60699 100644
--- a/magnifier/zoom-region.c
+++ b/magnifier/zoom-region.c
@@ -742,24 +742,27 @@ zoom_region_update_current (ZoomRegion *zoom_region)
 	}
 }
 
-static GdkRectangle
-zoom_region_cursor_rect (ZoomRegion *zoom_region)
+static void
+zoom_region_cursor_rect (ZoomRegion *zoom_region, GdkRectangle *rect, int *x, int *y)
 {
-	GdkRectangle rect = {0, 0, 0, 0};
+	GdkRectangle tmp;
 	Magnifier *magnifier = zoom_region->priv->parent;
-	GdkDrawable *cursor = NULL;
 	if (magnifier)
-		cursor = magnifier_get_cursor (magnifier);
-	if (cursor)
-	{
-		rect.x = zoom_region->priv->last_cursor_pos.x;
-		rect.y = zoom_region->priv->last_cursor_pos.y;
-		rect = zoom_region_view_rect_from_source_rect (zoom_region, rect);
-		rect.x -= magnifier->cursor_hotspot.x;
-		rect.y -= magnifier->cursor_hotspot.y;
-		gdk_drawable_get_size (cursor, &rect.width, &rect.height);
-	}
-	return rect;
+		magnifier_get_cursor_size (magnifier, rect);
+        else
+                memset (rect, 0, sizeof (GdkRectangle));
+
+        if (rect->width <= 0 || rect->height <= 0)
+                return;
+
+        tmp.x = zoom_region->priv->last_cursor_pos.x;
+        tmp.y = zoom_region->priv->last_cursor_pos.y;
+        tmp.width = tmp.height = 0;
+        tmp = zoom_region_view_rect_from_source_rect (zoom_region, tmp);
+        rect->x += tmp.x;
+        rect->y += tmp.y;
+        *x = tmp.x;
+        *y = tmp.y;
 }
 
 static void
@@ -797,12 +800,10 @@ zoom_region_paint_crosswire_cursor (ZoomRegion *zoom_region, GdkRectangle *clip_
 	static GdkColor last_color;
 	static gboolean last_color_init = FALSE;
 	GdkGCValues values;
-	GdkRectangle rect;
-	GdkDrawable *cursor;
+	GdkRectangle rect, crect;
 	GdkColor color = {0, 0, 0, 0};
 	int x_start = 0, y_start = 0, x_end = 4096, y_end = 4096;
 	int x_left_clip = 0, x_right_clip = 0, y_top_clip = 0, y_bottom_clip = 0;
-	int csize = 0;
 	
 #ifdef ZOOM_REGION_DEBUG
 	g_assert (zoom_region->alive);
@@ -864,22 +865,16 @@ zoom_region_paint_crosswire_cursor (ZoomRegion *zoom_region, GdkRectangle *clip_
 	if (clip_rect) gdk_gc_set_clip_rectangle (zoom_region->priv->crosswire_gc, clip_rect);
 	else gdk_gc_set_clip_rectangle (zoom_region->priv->crosswire_gc, NULL);
 
-	if ((cursor = magnifier_get_cursor (magnifier))) {
-		gdk_drawable_get_size (cursor, &csize, &csize);
-	}
+        magnifier_get_cursor_size (magnifier, &crect);
+        crect.x += rect.x;
+        crect.y += rect.y;
 
 	if (magnifier->crosswire_length) {
 		if (magnifier->crosswire_clip) {
-			x_start = rect.x - magnifier->cursor_hotspot.x -
-				magnifier->crosswire_length;
-			x_end = rect.x +
-				(csize - magnifier->cursor_hotspot.x) +
-				magnifier->crosswire_length;
-			y_start = rect.y - magnifier->cursor_hotspot.y -
-				magnifier->crosswire_length;
-			y_end = rect.y +
-				(csize - magnifier->cursor_hotspot.y) +
-				magnifier->crosswire_length;
+			x_start = crect.x - magnifier->crosswire_length;
+			x_end = crect.x + crect.width + magnifier->crosswire_length;
+			y_start = crect.y - magnifier->crosswire_length;
+			y_end = crect.y + crect.height + magnifier->crosswire_length;
 		} else {
 			x_start = rect.x - magnifier->crosswire_length;
 			x_end = rect.x + magnifier->crosswire_length;
@@ -890,16 +885,10 @@ zoom_region_paint_crosswire_cursor (ZoomRegion *zoom_region, GdkRectangle *clip_
 
 	if (magnifier->crosswire_clip)
 	{
-		y_top_clip = rect.y - magnifier->cursor_hotspot.y -
-			magnifier->crosswire_size;
-		y_bottom_clip = rect.y +
-			(csize - magnifier->cursor_hotspot.y) +
-			magnifier->crosswire_size;
-		x_left_clip = rect.x - magnifier->cursor_hotspot.x -
-			magnifier->crosswire_size;
-		x_right_clip = rect.x +
-			(csize - magnifier->cursor_hotspot.x) +
-			magnifier->crosswire_size;
+		y_top_clip = crect.y - magnifier->crosswire_size;
+		y_bottom_clip = crect.y + crect.height + magnifier->crosswire_size;
+		x_left_clip = rect.x - magnifier->crosswire_size;
+		x_right_clip = crect.x + crect.width + magnifier->crosswire_size;
 
 	}
 	if (magnifier->crosswire_size == 1) {
@@ -964,17 +953,19 @@ static void
 zoom_region_paint_cursor (ZoomRegion *zoom_region,
 			  GdkRectangle *clip_rect)
 {
-	GdkGCValues values;
 	GdkRectangle rect, intersct;
 	GdkRectangle fullscreen;
 	Magnifier *magnifier = zoom_region->priv->parent;
-	rect = zoom_region_cursor_rect (zoom_region);
+        int x, y;
+
 #ifdef ZOOM_REGION_DEBUG
 	g_assert (zoom_region->alive);
 #endif
 	if (!zoom_region->draw_cursor)
 		return;
 
+	zoom_region_cursor_rect (zoom_region, &rect, &x, &y);
+
 	if (clip_rect == NULL)
 	{
 		fullscreen = zoom_region_rect_from_bounds (zoom_region,
@@ -982,17 +973,18 @@ zoom_region_paint_cursor (ZoomRegion *zoom_region,
 		clip_rect = &fullscreen;
 	}
 	/* save the unclipped cursor pos for 'undrawing' the crosswire, the clipped one is no good */
-	zoom_region->priv->last_drawn_crosswire_pos.x = rect.x + magnifier->cursor_hotspot.x;
-	zoom_region->priv->last_drawn_crosswire_pos.y = rect.y + magnifier->cursor_hotspot.y;
+	zoom_region->priv->last_drawn_crosswire_pos.x = rect.x;
+	zoom_region->priv->last_drawn_crosswire_pos.y = rect.y;
 
 	if (gdk_rectangle_intersect (clip_rect, &rect, &intersct))
 	{
+                cairo_pattern_t *cursor;
 		int width = 0, height = 0;
 		
-		GdkDrawable *cursor = magnifier_get_cursor (magnifier);
+                cursor= magnifier_get_cursor (magnifier);
 		if (!cursor)
 			return;
-		else if (!GDK_IS_DRAWABLE (cursor)) g_message ("cursor isn't DRAWABLE!");
+
 		zoom_region->priv->cursor_backing_rect = rect;
 		if (zoom_region->priv->cursor_backing_pixels) {
 			gdk_drawable_get_size (zoom_region->priv->cursor_backing_pixels,
@@ -1023,32 +1015,21 @@ zoom_region_paint_cursor (ZoomRegion *zoom_region,
 				     rect.height);
 		}
 		DEBUG_RECT ("painting", rect);
-		if (cursor && GDK_IS_DRAWABLE (gtk_widget_get_window (GTK_WIDGET (zoom_region))))
+		if (GDK_IS_DRAWABLE (gtk_widget_get_window (GTK_WIDGET (zoom_region))))
 		{
-		    if (zoom_region->priv->paint_cursor_gc == NULL)
-			    zoom_region->priv->paint_cursor_gc = gdk_gc_new (gtk_widget_get_window (GTK_WIDGET (zoom_region)));
-
-			gdk_gc_set_clip_rectangle (zoom_region->priv->paint_cursor_gc, clip_rect);
-			values.clip_x_origin = rect.x;
-			values.clip_y_origin = rect.y;
-			values.clip_mask = magnifier->priv->cursor_mask;
-			gdk_gc_set_values(zoom_region->priv->paint_cursor_gc, &values, GDK_GC_CLIP_X_ORIGIN |
-					  GDK_GC_CLIP_Y_ORIGIN  | GDK_GC_CLIP_MASK);
-
-			gdk_draw_rectangle (gtk_widget_get_window (GTK_WIDGET (zoom_region)),
-					   zoom_region->priv->paint_cursor_gc,
-					   TRUE,
-					   rect.x, rect.y, rect.width, rect.height);
-
-			gdk_draw_drawable (gtk_widget_get_window (GTK_WIDGET (zoom_region)),
-					   zoom_region->priv->paint_cursor_gc,
-					   cursor,
-					   0, 0,
-					   rect.x,
-					   rect.y,
-					   rect.width,
-					   rect.height);
+                    cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (GTK_WIDGET (zoom_region)));
+
+                    gdk_cairo_rectangle (cr, clip_rect);
+                    cairo_clip (cr);
+
+                    cairo_translate (cr, x, y);
+                    cairo_set_source (cr, cursor);
+                    cairo_paint (cr);
+
+                    cairo_destroy (cr);
 		}
+
+                cairo_pattern_destroy (cursor);
 	}
 }
 



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