http://mail.gnome.org/archives/performance-list/2006-October/msg00063.html

From: Xan Lópe
To: ext Matt Hoosier
Cc: performance-list gnome org
Subject: Re: [patch] Remove pangocairo from Gtk+ 2.8.20
Date: Mon, 30 Oct 2006 14:31:56 +0200
Hi,

I've upgraded your patch against GTK+ 2.10.6, and we are getting great
performance figures compared to GTK+ 2.10.6 with pangocairo too
(basically at the level of GTK+ 2.6.10 again). Right now I'm working on
a python/cairo script to get some nice graphics from a torture test
session with several GTK+s, hope to get it ready soon.

Index: gtk+-2.10.6/configure.in
===================================================================
--- gtk+-2.10.6.orig/configure.in	2006-10-30 12:59:28.000000000 +0000
+++ gtk+-2.10.6/configure.in	2006-10-30 12:59:30.000000000 +0000
@@ -1435,7 +1435,7 @@
 if test "x$gdktarget" = "xwin32"; then
 	PANGO_PACKAGES="pangowin32 pangocairo"
 else
-	PANGO_PACKAGES="pango pangocairo"
+	PANGO_PACKAGES="pango pangocairo pangoxft"
 fi
 
 AC_MSG_CHECKING(Pango flags)
Index: gtk+-2.10.6/gdk/gdkaliasdef.c
===================================================================
--- gtk+-2.10.6.orig/gdk/gdkaliasdef.c	2006-10-30 12:58:29.000000000 +0000
+++ gtk+-2.10.6/gdk/gdkaliasdef.c	2006-10-30 12:59:30.000000000 +0000
@@ -1799,9 +1799,6 @@
 #undef gdk_pango_context_get 
 extern __typeof (gdk_pango_context_get) gdk_pango_context_get __attribute((alias("IA__gdk_pango_context_get"), visibility("default")));
 
-#undef gdk_pango_context_get_for_screen 
-extern __typeof (gdk_pango_context_get_for_screen) gdk_pango_context_get_for_screen __attribute((alias("IA__gdk_pango_context_get_for_screen"), visibility("default")));
-
 #ifndef GDK_DISABLE_DEPRECATED
 #undef gdk_pango_context_set_colormap 
 extern __typeof (gdk_pango_context_set_colormap) gdk_pango_context_set_colormap __attribute((alias("IA__gdk_pango_context_set_colormap"), visibility("default")));
@@ -1836,6 +1833,13 @@
 
 #endif
 #endif
+#if IN_HEADER(__GDK_PANGO_H__)
+#if IN_FILE(__GDK_PANGO_X11_C__)
+#undef gdk_pango_context_get_for_screen 
+extern __typeof (gdk_pango_context_get_for_screen) gdk_pango_context_get_for_screen __attribute((alias("IA__gdk_pango_context_get_for_screen"), visibility("default")));
+
+#endif
+#endif
 #if IN_HEADER(__GDK_PIXBUF_H__)
 #if IN_FILE(__GDK_PIXBUF_DRAWABLE_C__)
 #undef gdk_pixbuf_get_from_drawable 
Index: gtk+-2.10.6/gdk/gdkalias.h
===================================================================
--- gtk+-2.10.6.orig/gdk/gdkalias.h	2006-10-30 12:58:29.000000000 +0000
+++ gtk+-2.10.6/gdk/gdkalias.h	2006-10-30 12:59:30.000000000 +0000
@@ -1796,9 +1796,6 @@
 extern __typeof (gdk_pango_context_get) IA__gdk_pango_context_get __attribute((visibility("hidden")));
 #define gdk_pango_context_get IA__gdk_pango_context_get
 
-extern __typeof (gdk_pango_context_get_for_screen) IA__gdk_pango_context_get_for_screen __attribute((visibility("hidden")));
-#define gdk_pango_context_get_for_screen IA__gdk_pango_context_get_for_screen
-
 #ifndef GDK_DISABLE_DEPRECATED
 extern __typeof (gdk_pango_context_set_colormap) IA__gdk_pango_context_set_colormap __attribute((visibility("hidden")));
 #define gdk_pango_context_set_colormap IA__gdk_pango_context_set_colormap
@@ -1833,6 +1830,13 @@
 
 #endif
 #endif
+#if IN_HEADER(__GDK_PANGO_H__)
+#if IN_FILE(__GDK_PANGO_X11_C__)
+extern __typeof (gdk_pango_context_get_for_screen) IA__gdk_pango_context_get_for_screen __attribute((visibility("hidden")));
+#define gdk_pango_context_get_for_screen IA__gdk_pango_context_get_for_screen
+
+#endif
+#endif
 #if IN_HEADER(__GDK_PIXBUF_H__)
 #if IN_FILE(__GDK_PIXBUF_DRAWABLE_C__)
 extern __typeof (gdk_pixbuf_get_from_drawable) IA__gdk_pixbuf_get_from_drawable __attribute((visibility("hidden")));
Index: gtk+-2.10.6/gdk/gdkdraw.c
===================================================================
--- gtk+-2.10.6.orig/gdk/gdkdraw.c	2006-10-30 12:58:29.000000000 +0000
+++ gtk+-2.10.6/gdk/gdkdraw.c	2006-10-30 12:59:30.000000000 +0000
@@ -909,9 +909,9 @@
 {
   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
   g_return_if_fail (GDK_IS_GC (gc));
-  
-  real_draw_glyphs (drawable, gc, NULL, font,
-		    x, y, glyphs);
+
+
+  GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs (drawable, gc, font, x, y, glyphs);
 }
 
 /**
@@ -949,8 +949,9 @@
   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
   g_return_if_fail (GDK_IS_GC (gc));
 
-  real_draw_glyphs (drawable, gc, matrix, font,
-		    x / PANGO_SCALE, y / PANGO_SCALE, glyphs);
+  if (GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs_transformed)
+    GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs_transformed (drawable, gc, matrix,
+								font, x, y, glyphs);
 }
 
 /**
@@ -974,28 +975,12 @@
 		     GdkTrapezoid   *trapezoids,
 		     gint            n_trapezoids)
 {
-  cairo_t *cr;
-  int i;
-
   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
   g_return_if_fail (GDK_IS_GC (gc));
   g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL);
 
-  cr = gdk_cairo_create (drawable);
-  _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE);
-  
-  for (i = 0; i < n_trapezoids; i++)
-    {
-      cairo_move_to (cr, trapezoids[i].x11, trapezoids[i].y1);
-      cairo_line_to (cr, trapezoids[i].x21, trapezoids[i].y1);
-      cairo_line_to (cr, trapezoids[i].x22, trapezoids[i].y2);
-      cairo_line_to (cr, trapezoids[i].x21, trapezoids[i].y2);
-      cairo_close_path (cr);
-    }
-
-  cairo_fill (cr);
-
-  cairo_destroy (cr);
+  GDK_DRAWABLE_GET_CLASS (drawable)->draw_trapezoids (drawable, gc,
+						      trapezoids, n_trapezoids);
 }
 
 /**
Index: gtk+-2.10.6/gdk/gdkpango.c
===================================================================
--- gtk+-2.10.6.orig/gdk/gdkpango.c	2006-10-30 12:58:29.000000000 +0000
+++ gtk+-2.10.6/gdk/gdkpango.c	2006-10-30 12:59:30.000000000 +0000
@@ -50,19 +50,34 @@
   GdkBitmap *stipple[MAX_RENDER_PART + 1];
   gboolean embossed;
 
-  cairo_t *cr;
-  PangoRenderPart last_part;
+  /* When switching between the normal and shadow copies when
+   * drawing shadows we can get unexpected recursion into the
+   * drawing functions; the 'in_emboss' flag guards against that.
+   */
+  gboolean in_emboss;
 
   /* Current target */
   GdkDrawable *drawable;
   GdkGC *base_gc;
 
   gboolean gc_changed;
+    
+  /* Cached GC, derived from base_gc */
+  GdkGC *gc;
+  PangoColor gc_color;
+  gboolean gc_color_set;
+  GdkBitmap *gc_stipple;
+  
+  /* we accumulate trapezoids for the same PangoRenderPart */
+  GArray *trapezoids;
+  PangoRenderPart trapezoid_part;
 };
 
 static PangoAttrType gdk_pango_attr_stipple_type;
 static PangoAttrType gdk_pango_attr_embossed_type;
 
+static void flush_trapezoids (GdkPangoRenderer *gdk_renderer);
+
 enum {
   PROP_0,
   PROP_SCREEN
@@ -77,6 +92,10 @@
   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
   int i;
 
+  if (priv->gc)
+    g_object_unref (priv->gc);
+  if (priv->gc_stipple)
+    g_object_unref (priv->gc_stipple);
   if (priv->base_gc)
     g_object_unref (priv->base_gc);
   if (priv->drawable)
@@ -86,6 +105,8 @@
     if (priv->stipple[i])
       g_object_unref (priv->stipple[i]);
 
+  g_array_free (priv->trapezoids, TRUE);
+    
   G_OBJECT_CLASS (gdk_pango_renderer_parent_class)->finalize (object);
 }
 
@@ -112,25 +133,6 @@
   return object;
 }
 
-/* Adjusts matrix and color for the renderer to draw the secondary
- * "shadow" copy for embossed text */
-static void
-emboss_context (cairo_t *cr)
-{
-  cairo_matrix_t tmp_matrix;
-
-  /* The gymnastics here to adjust the matrix are because we want
-   * to offset by +1,+1 in device-space, not in user-space,
-   * so we can't just draw the layout at x + 1, y + 1
-   */
-  cairo_get_matrix (cr, &tmp_matrix);
-  tmp_matrix.x0 += 1.0;
-  tmp_matrix.y0 += 1.0;
-  cairo_set_matrix (cr, &tmp_matrix);
-
-  cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
-}
-
 static inline gboolean
 color_equal (PangoColor *c1, PangoColor *c2)
 {
@@ -146,74 +148,154 @@
   return FALSE;
 }
 
-static cairo_t *
-get_cairo_context (GdkPangoRenderer *gdk_renderer,
-		   PangoRenderPart   part)
+/* Adjusts matrix and color for the renderer to draw the secondar
+ * "shadow" copy for embossed text */
+static void
+emboss_renderer (PangoRenderer   *renderer,
+		 PangoRenderPart  part,
+		 PangoMatrix    **save_matrix,
+		 PangoColor     **save_color)
+{
+  GdkPangoRendererPrivate *priv = GDK_PANGO_RENDERER(renderer)->priv;
+  static const PangoColor white = { 0xffff, 0xffff, 0xffff };
+  PangoMatrix tmp_matrix = PANGO_MATRIX_INIT;
+
+  priv->in_emboss = TRUE;
+  
+  *save_color = pango_renderer_get_color (renderer, part);
+  if (*save_color)
+    *save_color = pango_color_copy (*save_color);
+  
+  *save_matrix = renderer->matrix;
+  if (*save_matrix)
+    {
+      *save_matrix = pango_matrix_copy (*save_matrix);
+      tmp_matrix = **save_matrix;
+    }
+  
+  /* The gymnastics here to adjust the matrix are because we want
+   * to offset by +1,+1 in device-space, not in user-space,
+   * so we can't just draw the layout at x + 1, y + 1
+   */
+  tmp_matrix.x0 += 1;
+  tmp_matrix.y0 += 1;
+  
+  pango_renderer_set_matrix (renderer, &tmp_matrix);
+  pango_renderer_set_color (renderer, part, &white);
+}
+
+/* Restores from emboss_renderer() */
+static void
+unemboss_renderer (PangoRenderer   *renderer,
+		   PangoRenderPart  part,
+		   PangoMatrix    **save_matrix,
+		   PangoColor     **save_color)
+{
+  GdkPangoRendererPrivate *priv = GDK_PANGO_RENDERER(renderer)->priv;
+  pango_renderer_set_matrix (renderer, *save_matrix);
+  pango_renderer_set_color (renderer, part, *save_color);
+
+  if (*save_matrix)
+    pango_matrix_free (*save_matrix);
+  if (*save_color)
+    pango_color_free (*save_color);
+
+  priv->in_emboss = FALSE;
+}
+
+/* Gets the GC for drawing @part. This make involve copying the base GC
+ * for the renderer, in which case we keep a one-GC cache. */
+static GdkGC *
+get_gc (GdkPangoRenderer *gdk_renderer,
+	PangoRenderPart   part)
 {
   PangoRenderer *renderer = PANGO_RENDERER (gdk_renderer);
+  PangoColor *color;
+  GdkBitmap *stipple;
   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
 
-  if (!priv->cr)
+  color = pango_renderer_get_color (renderer, part);
+
+  if (part <= MAX_RENDER_PART)
+    stipple = priv->stipple[part];
+  else
+    stipple = NULL;
+
+  if (!color && !stipple)	/* nothing override, use base_gc */
+    return priv->base_gc;
+  else
     {
-      const PangoMatrix *matrix;
+      gboolean new_stipple = FALSE;
+      gboolean new_color = FALSE;
       
-      priv->cr = gdk_cairo_create (priv->drawable);
+      if (stipple != priv->gc_stipple)
+	new_stipple = TRUE;
 
-      matrix = pango_renderer_get_matrix (renderer);
-      if (matrix)
+      if ((priv->gc_color_set && !color) ||
+	  (!priv->gc_color_set && color) ||
+	  priv->gc_color.red != color->red ||
+	  priv->gc_color.green != color->green ||
+	  priv->gc_color.blue != color->blue)
+	new_color = TRUE;
+      
+      if (!priv->gc)
 	{
-	  cairo_matrix_t cairo_matrix;
-	  
-	  cairo_matrix_init (&cairo_matrix,
-			     matrix->xx, matrix->yx,
-			     matrix->xy, matrix->yy,
-			     matrix->x0, matrix->y0);
-	  cairo_set_matrix (priv->cr, &cairo_matrix);
+	  priv->gc = gdk_gc_new (priv->drawable);
+	  gdk_gc_copy (priv->gc, priv->base_gc);
+	}
+      else if (new_color && priv->gc_color_set && !color)
+	{
+	  /* We have to recopy the original GC onto the cached GC
+	   * to get the default color */
+	  new_stipple = TRUE;
+	  gdk_gc_copy (priv->gc, priv->base_gc);
+	}
+      else if (new_stipple && priv->gc_stipple && !stipple)
+	{
+	  /* Similarly, we need to make a new copy to restore to the
+	   * default stipple state (the caller may have set a stipple
+	   * on the GC, and even if not, gdk_gc_set_stipple (gc, NULL)
+	   * doesn't work currently to restore to the default X stipple) */
+	  new_color = TRUE;
+	  gdk_gc_copy (priv->gc, priv->base_gc);
 	}
-    }
-
-  if (part != priv->last_part)
-    {
-      PangoColor *pango_color;
-      GdkColor *color;
-      GdkColor tmp_color;
-      gboolean changed;
 
-      pango_color = pango_renderer_get_color (renderer, part);
-      
-      if (priv->last_part != -1)
-	changed = priv->gc_changed ||
-	  priv->stipple[priv->last_part] != priv->stipple[part] ||
-	  !color_equal (pango_color,
-			pango_renderer_get_color (renderer, priv->last_part));
-      else
-	changed = TRUE;
-      
-      if (changed)
+      if (new_color)
 	{
-	  if (pango_color)
+	  if (color)
 	    {
-	      tmp_color.red = pango_color->red;
-	      tmp_color.green = pango_color->green;
-	      tmp_color.blue = pango_color->blue;
+	      GdkColor gdk_color;
+
+	      gdk_color.red = color->red;
+	      gdk_color.green = color->green;
+	      gdk_color.blue = color->blue;
 	      
-	      color = &tmp_color;
+	      gdk_gc_set_rgb_fg_color (priv->gc, &gdk_color);
+
+	      priv->gc_color = *color;
+	      priv->gc_color_set = TRUE;
 	    }
 	  else
-	    color = NULL;
+	    priv->gc_color_set = FALSE;
+	}
 
-	  _gdk_gc_update_context (priv->base_gc,
-				  priv->cr,
-				  color,
-				  priv->stipple[part],
-				  priv->gc_changed);
+      if (new_stipple)
+	{
+	  if (priv->gc_stipple)
+	    g_object_unref (priv->gc_stipple);
+
+	  if (stipple)
+	    {
+	      gdk_gc_set_stipple (priv->gc, stipple);
+	      gdk_gc_set_fill (priv->gc, GDK_STIPPLED);
+	      priv->gc_stipple = g_object_ref (stipple);
+	    }
+	  else
+	    priv->gc_stipple = NULL;
 	}
 
-      priv->last_part = part;
-      priv->gc_changed = FALSE;
+      return priv->gc;
     }
-
-  return priv->cr;
 }
 
 static void
@@ -225,133 +307,78 @@
 {
   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
-  cairo_t *cr;
 
-  cr = get_cairo_context (gdk_renderer, 
-			  PANGO_RENDER_PART_FOREGROUND);
+  flush_trapezoids (gdk_renderer);
 
-  if (priv->embossed)
+  if (!priv->in_emboss && priv->embossed)
     {
-      cairo_save (cr);
-      emboss_context (cr);
-      cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
-      pango_cairo_show_glyph_string (cr, font, glyphs);
-      cairo_restore (cr);
-    }
-  
-  cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
-  pango_cairo_show_glyph_string (cr, font, glyphs);
-}
-
-/* Draws an error underline that looks like one of:
- *              H       E                H
- *     /\      /\      /\        /\      /\               -
- *   A/  \    /  \    /  \     A/  \    /  \              |
- *    \   \  /    \  /   /D     \   \  /    \             |
- *     \   \/  C   \/   /        \   \/   C  \            | height = HEIGHT_SQUARES * square
- *      \      /\  F   /          \  F   /\   \           | 
- *       \    /  \    /            \    /  \   \G         |
- *        \  /    \  /              \  /    \  /          |
- *         \/      \/                \/      \/           -
- *         B                         B       
- *    |----|
- *   unit_width = (HEIGHT_SQUARES - 1) * square
- *
- * The x, y, width, height passed in give the desired bounding box;
- * x/width are adjusted to make the underline a integer number of units
- * wide.
- */
-#define HEIGHT_SQUARES 2.5
+      PangoMatrix *save_matrix;
+      PangoColor *save_color;
 
-/* Cut-and-pasted between here and pango/pango/pangocairo-render.c */
+      emboss_renderer (renderer, PANGO_RENDER_PART_FOREGROUND, &save_matrix, &save_color);
+      gdk_draw_glyphs_transformed (priv->drawable,
+				   get_gc (gdk_renderer, PANGO_RENDER_PART_FOREGROUND),
+				   renderer->matrix, font, x, y, glyphs);
+      unemboss_renderer (renderer, PANGO_RENDER_PART_FOREGROUND, &save_matrix, &save_color);
+    }
+
+  gdk_draw_glyphs_transformed (priv->drawable,
+			       get_gc (gdk_renderer, PANGO_RENDER_PART_FOREGROUND),
+			       renderer->matrix, font, x, y, glyphs);
+}
+
+/* Outputs any pending trapezoids, we do this when the part or
+ * part color changes, when we are about to draw text, etc. */
 static void
-draw_error_underline (cairo_t *cr,
-		      double  x,
-		      double  y,
-		      double  width,
-		      double  height)
-{
-  double square = height / HEIGHT_SQUARES;
-  double unit_width = (HEIGHT_SQUARES - 1) * square;
-  int width_units = (width + unit_width / 2) / unit_width;
-  double y_top, y_bottom;
-  int i;
+flush_trapezoids (GdkPangoRenderer *gdk_renderer)
+{
+  GdkPangoRendererPrivate *priv = gdk_renderer->priv;
 
-  x += (width - width_units * unit_width) / 2;
-  width = width_units * unit_width;
+  if (!priv->trapezoids || priv->trapezoids->len == 0)
+    return;
 
-  y_top = y;
-  y_bottom = y + height;
-  
-  /* Bottom of squiggle */
-  cairo_move_to (cr, x - square / 2, y_top + square / 2); /* A */
-  for (i = 0; i < width_units; i += 2)
-    {
-      double x_middle = x + (i + 1) * unit_width;
-      double x_right = x + (i + 2) * unit_width;
-    
-      cairo_line_to (cr, x_middle, y_bottom); /* B */
-      
-      if (i + 1 == width_units)
-	/* Nothing */;
-      else if (i + 2 == width_units)
-	cairo_line_to (cr, x_right + square / 2, y_top + square / 2); /* D */
-      else
-	cairo_line_to (cr, x_right, y_top + square); /* C */
-    }
-  
-  /* Top of squiggle */
-  for (i -= 2; i >= 0; i -= 2)
-    {
-      double x_left = x + i * unit_width;
-      double x_middle = x + (i + 1) * unit_width;
-      double x_right = x + (i + 2) * unit_width;
-      
-      if (i + 1 == width_units)
-	cairo_line_to (cr, x_middle + square / 2, y_bottom - square / 2); /* G */
-      else {
-	if (i + 2 == width_units)
-	  cairo_line_to (cr, x_right, y_top); /* E */
-	cairo_line_to (cr, x_middle, y_bottom - square); /* F */
-      }
-      
-      cairo_line_to (cr, x_left, y_top);   /* H */
-    }
+  gdk_draw_trapezoids (priv->drawable,
+		       get_gc (gdk_renderer, priv->trapezoid_part),
+		       (GdkTrapezoid *)priv->trapezoids->data,
+		       priv->trapezoids->len);
 
-  cairo_close_path (cr);
-  cairo_fill (cr);
+  g_array_set_size (priv->trapezoids, 0);
 }
 
+/* Draws a single trapezoid ... we don't draw it immediately, but rather
+ * cache it to join together with other trapezoids that form part of the
+ * same logical shape */
 static void
-gdk_pango_renderer_draw_rectangle (PangoRenderer    *renderer,
-				   PangoRenderPart   part,
-				   int               x,
-				   int               y,
-				   int               width,
-				   int               height)
+gdk_pango_renderer_draw_trapezoid (PangoRenderer   *renderer,
+				   PangoRenderPart  part,
+				   double           y1,
+				   double           x11,
+				   double           x21,
+				   double           y2,
+				   double           x12,
+				   double           x22)
 {
   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
-  GdkPangoRendererPrivate *priv = gdk_renderer->priv;
-  cairo_t *cr;
-  
-  cr = get_cairo_context (gdk_renderer, part);
-
-  if (priv->embossed && part != PANGO_RENDER_PART_BACKGROUND)
-    {
-      cairo_save (cr);
-      emboss_context (cr);
-      cairo_rectangle (cr,
-		       (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
-		       (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
+  GdkTrapezoid trap;
 
-      cairo_fill (cr);
-      cairo_restore (cr);
-    }
+  if (!gdk_renderer->priv->trapezoids)
+    gdk_renderer->priv->trapezoids = g_array_new (FALSE, FALSE,
+						  sizeof (GdkTrapezoid));
+  
+  if (gdk_renderer->priv->trapezoids->len > 0 &&
+      gdk_renderer->priv->trapezoid_part != part)
+    flush_trapezoids (gdk_renderer);
+  
+  gdk_renderer->priv->trapezoid_part = part;
+
+  trap.y1 = y1;
+  trap.x11 = x11 / 2;
+  trap.x21 = x21;
+  trap.y2 = y2;
+  trap.x12 = x12;
+  trap.x22 = x22;
 
-  cairo_rectangle (cr,
-		   (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
-		   (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
-  cairo_fill (cr);
+  g_array_append_val (gdk_renderer->priv->trapezoids, trap);
 }
 
 static void
@@ -363,23 +390,51 @@
 {
   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
-  cairo_t *cr;
-  
-  cr = get_cairo_context (gdk_renderer, PANGO_RENDER_PART_UNDERLINE);
-  
-  if (priv->embossed)
+
+  if (!priv->in_emboss && priv->embossed)
     {
-      cairo_save (cr);
-      emboss_context (cr);
-      draw_error_underline (cr,
-			    (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
-			    (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
-      cairo_restore (cr);
+      PangoMatrix *save_matrix;
+      PangoColor *save_color;
+
+      emboss_renderer (renderer, PANGO_RENDER_PART_UNDERLINE, &save_matrix, &save_color);
+      PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_error_underline (renderer,
+										    x, y, width, height);
+      unemboss_renderer (renderer, PANGO_RENDER_PART_UNDERLINE, &save_matrix, &save_color);
     }
 
-  draw_error_underline (cr,
-			(double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
-			(double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
+  PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_error_underline (renderer,
+										x, y, width, height);
+}
+
+/* We can't handle embossing at the level of trapezoids, because when an
+ * underline is split into multiple trapezoids, the normal and shadow
+ * trapezoids will be drawn mixed together. Instead, we have to emboss
+ * and entire rectangle or error underline
+ */
+static void
+gdk_pango_renderer_draw_rectangle (PangoRenderer    *renderer,
+				   PangoRenderPart   part,
+				   int               x,
+				   int               y,
+				   int               width,
+				   int               height)
+{
+  GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
+  GdkPangoRendererPrivate *priv = gdk_renderer->priv;
+
+  if (!priv->in_emboss && priv->embossed && part != PANGO_RENDER_PART_BACKGROUND)
+    {
+      PangoMatrix *save_matrix;
+      PangoColor *save_color;
+
+      emboss_renderer (renderer, part, &save_matrix, &save_color);
+      PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_rectangle (renderer, part,
+									      x, y, width, height);
+      unemboss_renderer (renderer, part, &save_matrix, &save_color);
+    }
+
+  PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_rectangle (renderer, part,
+									  x, y, width, height);
 }
 
 static void
@@ -388,8 +443,8 @@
 {
   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
 
-  if (gdk_renderer->priv->last_part == part)
-    gdk_renderer->priv->last_part = (PangoRenderPart)-1;
+  if (part == gdk_renderer->priv->trapezoid_part)
+    flush_trapezoids (gdk_renderer);
 }
 
 static void
@@ -410,13 +465,8 @@
 {
   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
-
-  if (priv->cr)
-    {
-      cairo_destroy (priv->cr);
-      priv->cr = NULL;
-    }
-  priv->last_part = (PangoRenderPart)-1;
+    
+  flush_trapezoids (gdk_renderer);
 }
 
 static void
@@ -515,7 +565,6 @@
 						GDK_TYPE_PANGO_RENDERER,
 						GdkPangoRendererPrivate);
 
-  renderer->priv->last_part = (PangoRenderPart)-1;
   renderer->priv->gc_changed = TRUE;
 }
 
@@ -527,6 +576,7 @@
   PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
   
   renderer_class->draw_glyphs = gdk_pango_renderer_draw_glyphs;
+  renderer_class->draw_trapezoid = gdk_pango_renderer_draw_trapezoid;
   renderer_class->draw_rectangle = gdk_pango_renderer_draw_rectangle;
   renderer_class->draw_error_underline = gdk_pango_renderer_draw_error_underline;
   renderer_class->part_changed = gdk_pango_renderer_part_changed;
@@ -647,6 +697,8 @@
 
   priv = gdk_renderer->priv;
   
+  flush_trapezoids (gdk_renderer);
+    
   if (priv->drawable != drawable)
     {
       if (priv->drawable)
@@ -681,6 +733,8 @@
 
   priv = gdk_renderer->priv;
   
+  flush_trapezoids (gdk_renderer);
+    
   if (priv->base_gc != gc)
     {
       if (priv->base_gc)
@@ -689,6 +743,20 @@
       if (priv->base_gc)
 	g_object_ref (priv->base_gc);
 
+      if (priv->gc)
+	{
+	  g_object_unref (priv->gc);
+	  priv->gc = NULL;
+	}
+        
+      priv->gc_color_set = FALSE;
+
+      if (priv->gc_stipple)
+	{
+	  g_object_unref (priv->gc_stipple);
+	  priv->gc_stipple = NULL;
+	}
+        
       priv->gc_changed = TRUE;
     }
 }
@@ -1414,50 +1482,5 @@
   return gdk_pango_context_get_for_screen (gdk_screen_get_default ());
 }
 
-/**
- * gdk_pango_context_get_for_screen:
- * @screen: the #GdkScreen for which the context is to be created.
- * 
- * Creates a #PangoContext for @screen.
- *
- * The context must be freed when you're finished with it.
- * 
- * When using GTK+, normally you should use gtk_widget_get_pango_context()
- * instead of this function, to get the appropriate context for
- * the widget you intend to render text onto.
- * 
- * The newly created context will have the default font options
- * (see #cairo_font_options_t) for the screen; if these options
- * change it will not be updated. Using gtk_widget_get_pango_context()
- * is more convenient if you want to keep a context around and track
- * changes to the screen's font rendering settings.
- * 
- * Return value: a new #PangoContext for @screen
- *
- * Since: 2.2
- **/
-PangoContext *
-gdk_pango_context_get_for_screen (GdkScreen *screen)
-{
-  PangoFontMap *fontmap;
-  PangoContext *context;
-  const cairo_font_options_t *options;
-  double dpi;
-  
-  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
-
-  fontmap = pango_cairo_font_map_get_default ();
-  
-  context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
-
-  options = gdk_screen_get_font_options (screen);
-  pango_cairo_context_set_font_options (context, options);
-
-  dpi = gdk_screen_get_resolution (screen);
-  pango_cairo_context_set_resolution (context, dpi);
-
-  return context;
-}
-
 #define __GDK_PANGO_C__
 #include "gdkaliasdef.c"
Index: gtk+-2.10.6/gdk/gdk.symbols
===================================================================
--- gtk+-2.10.6.orig/gdk/gdk.symbols	2006-10-30 12:58:29.000000000 +0000
+++ gtk+-2.10.6/gdk/gdk.symbols	2006-10-30 12:59:30.000000000 +0000
@@ -861,7 +861,6 @@
 gdk_pango_attr_embossed_new
 gdk_pango_attr_stipple_new
 gdk_pango_context_get
-gdk_pango_context_get_for_screen
 #ifndef GDK_DISABLE_DEPRECATED
 gdk_pango_context_set_colormap
 #endif
@@ -877,6 +876,12 @@
 #endif
 #endif
 
+#if IN_HEADER(__GDK_PANGO_H__)
+#if IN_FILE(__GDK_PANGO_X11_C__)
+gdk_pango_context_get_for_screen
+#endif
+#endif
+
 #if IN_HEADER(__GDK_PIXBUF_H__)
 #if IN_FILE(__GDK_PIXBUF_DRAWABLE_C__)
 gdk_pixbuf_get_from_drawable
Index: gtk+-2.10.6/gdk/gdkwindow.c
===================================================================
--- gtk+-2.10.6.orig/gdk/gdkwindow.c	2006-10-30 12:58:29.000000000 +0000
+++ gtk+-2.10.6/gdk/gdkwindow.c	2006-10-30 12:59:30.000000000 +0000
@@ -1834,9 +1834,14 @@
     }
   else
     {
-      method->cr = cairo_create (paint->surface);
+      /*method->cr = cairo_create (paint->surface);
 
-      gdk_cairo_set_source_color (method->cr, &private->bg_color);
+      gdk_cairo_set_source_color (method->cr, &private->bg_color);*/
+      GdkGC *gc = _gdk_drawable_get_scratch_gc (paint->pixmap, FALSE);
+
+      gdk_gc_set_foreground (gc, &(private->bg_color));
+      
+      method->gc = g_object_ref (gc);
     }
 }
 
Index: gtk+-2.10.6/gdk/x11/gdkdisplay-x11.c
===================================================================
--- gtk+-2.10.6.orig/gdk/x11/gdkdisplay-x11.c	2006-10-30 12:58:29.000000000 +0000
+++ gtk+-2.10.6/gdk/x11/gdkdisplay-x11.c	2006-10-30 12:59:30.000000000 +0000
@@ -190,7 +190,8 @@
   display_x11->leader_window_title_set = FALSE;
 
   display_x11->have_render = GDK_UNKNOWN;
-
+  display_x11->have_render_with_trapezoids = GDK_UNKNOWN;
+  
 #ifdef HAVE_XFIXES
   if (XFixesQueryExtension (display_x11->xdisplay, 
 			    &display_x11->xfixes_event_base, 
Index: gtk+-2.10.6/gdk/x11/gdkdisplay-x11.h
===================================================================
--- gtk+-2.10.6.orig/gdk/x11/gdkdisplay-x11.h	2006-10-30 12:58:29.000000000 +0000
+++ gtk+-2.10.6/gdk/x11/gdkdisplay-x11.h	2006-10-30 12:59:30.000000000 +0000
@@ -78,6 +78,7 @@
   gboolean use_xshm;
   gboolean have_shm_pixmaps;
   GdkTristate have_render;
+  GdkTristate have_render_with_trapezoids;
   gboolean have_xfixes;
   gint xfixes_event_base;
 
Index: gtk+-2.10.6/gdk/x11/gdkdrawable-x11.c
===================================================================
--- gtk+-2.10.6.orig/gdk/x11/gdkdrawable-x11.c	2006-10-30 12:58:30.000000000 +0000
+++ gtk+-2.10.6/gdk/x11/gdkdrawable-x11.c	2006-10-30 12:59:30.000000000 +0000
@@ -26,6 +26,8 @@
 
 #include <config.h>
 
+#include <pango/pangoxft.h>
+
 #include "gdkx.h"
 #include "gdkregion-generic.h"
 
@@ -106,7 +108,21 @@
 				    GdkGC          *gc,
 				    GdkPoint       *points,
 				    gint            npoints);
-
+					
+static void gdk_x11_draw_glyphs             (GdkDrawable      *drawable,
+					     GdkGC            *gc,
+					     PangoFont        *font,
+					     gint              x,
+					     gint              y,
+					     PangoGlyphString *glyphs);
+static void gdk_x11_draw_glyphs_transformed (GdkDrawable      *drawable,
+					     GdkGC            *gc,
+					     PangoMatrix      *matrix,
+					     PangoFont        *font,
+					     gint              x,
+					     gint              y,
+					     PangoGlyphString *glyphs);
+						 
 static void gdk_x11_draw_image     (GdkDrawable     *drawable,
                                     GdkGC           *gc,
                                     GdkImage        *image,
@@ -129,6 +145,11 @@
 				    gint             x_dither,
 				    gint             y_dither);
 
+static void gdk_x11_draw_trapezoids (GdkDrawable     *drawable,
+				     GdkGC	     *gc,
+				     GdkTrapezoid    *trapezoids,
+				     gint             n_trapezoids);
+
 static cairo_surface_t *gdk_x11_ref_cairo_surface (GdkDrawable *drawable);
      
 static void gdk_x11_set_colormap   (GdkDrawable    *drawable,
@@ -163,8 +184,11 @@
   drawable_class->draw_points = gdk_x11_draw_points;
   drawable_class->draw_segments = gdk_x11_draw_segments;
   drawable_class->draw_lines = gdk_x11_draw_lines;
+  drawable_class->draw_glyphs = gdk_x11_draw_glyphs;
+  drawable_class->draw_glyphs_transformed = gdk_x11_draw_glyphs_transformed;
   drawable_class->draw_image = gdk_x11_draw_image;
   drawable_class->draw_pixbuf = gdk_x11_draw_pixbuf;
+  drawable_class->draw_trapezoids = gdk_x11_draw_trapezoids;
   
   drawable_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
 
@@ -327,6 +351,72 @@
   return x11display->have_render == GDK_YES;
 }
 
+gboolean
+_gdk_x11_have_render_with_trapezoids (GdkDisplay *display)
+{
+  Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
+  GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
+
+  if (x11display->have_render_with_trapezoids == GDK_UNKNOWN)
+    {
+      x11display->have_render_with_trapezoids = GDK_NO;
+      if (_gdk_x11_have_render (display))
+	{
+	  /*
+	   * Require protocol >= 0.4 for CompositeTrapezoids support.
+	   */
+	  int major_version, minor_version;
+	
+#define XRENDER_TETRAPEZOIDS_MAJOR 0
+#define XRENDER_TETRAPEZOIDS_MINOR 4
+	
+	  if (XRenderQueryVersion (xdisplay, &major_version,
+				   &minor_version))
+	    if ((major_version == XRENDER_TETRAPEZOIDS_MAJOR) &&
+		(minor_version >= XRENDER_TETRAPEZOIDS_MINOR))
+	      x11display->have_render_with_trapezoids = GDK_YES;
+	}
+    }
+
+  return x11display->have_render_with_trapezoids == GDK_YES;
+}
+
+static XftDraw *
+gdk_x11_drawable_get_xft_draw (GdkDrawable *drawable)
+{
+  GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+
+   if (impl->xft_draw == NULL)
+    {
+      GdkColormap *colormap = gdk_drawable_get_colormap (drawable);
+      
+      if (colormap)
+	{
+          GdkVisual *visual;
+
+          visual = gdk_colormap_get_visual (colormap);
+      
+          impl->xft_draw = XftDrawCreate (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
+ 				          GDK_VISUAL_XVISUAL (visual), GDK_COLORMAP_XCOLORMAP (colormap));
+	}
+      else if (gdk_drawable_get_depth (drawable) == 1)
+	{
+	  impl->xft_draw = XftDrawCreateBitmap (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid);
+	}
+      else
+        {
+	  g_warning ("Using Xft rendering requires the drawable argument to\n"
+		     "have a specified colormap. All windows have a colormap,\n"
+		     "however, pixmaps only have colormap by default if they\n"
+		     "were created with a non-NULL window argument. Otherwise\n"
+		     "a colormap must be set on them with gdk_drawable_set_colormap");
+	  return NULL;
+        }
+    }
+
+   return impl->xft_draw;
+}
+
 static Picture
 gdk_x11_drawable_get_picture (GdkDrawable *drawable)
 {
@@ -393,6 +483,57 @@
     }
 }
 
+static void
+gdk_x11_drawable_update_xft_clip (GdkDrawable *drawable,
+				   GdkGC       *gc)
+{
+  XftDraw *xft_draw = gdk_x11_drawable_get_xft_draw (drawable);
+  GdkRegion *clip_region = _gdk_gc_get_clip_region (gc);
+    
+  if (gc && clip_region)
+    {
+      GdkRegionBox *boxes = clip_region->rects;
+      gint n_boxes = clip_region->numRects;
+#if 0				/* Until XftDrawSetClipRectangles is there */
+      XRectangle *rects = g_new (XRectangle, n_boxes);
+      int i;
+
+      for (i=0; i < n_boxes; i++)
+	{
+	  rects[i].x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
+	  rects[i].y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
+	  rects[i].width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rects[i].x;
+	  rects[i].height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rects[i].y;
+	}
+      XftDrawSetClipRectangles (xft_draw, 0, 0, rects, n_boxes);
+
+      g_free (rects);
+#else
+      Region xregion = XCreateRegion ();
+      int i;
+ 
+      for (i=0; i < n_boxes; i++)
+ 	{
+ 	  XRectangle rect;
+ 	  
+ 	  rect.x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
+ 	  rect.y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
+ 	  rect.width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rect.x;
+ 	  rect.height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rect.y;
+	  
+ 	  XUnionRectWithRegion (&rect, xregion, xregion);
+ 	}
+      
+      XftDrawSetClip (xft_draw, xregion);
+      XDestroyRegion (xregion);
+#endif      
+    }
+  else
+    {
+      XftDrawSetClip (xft_draw, NULL);
+    }
+}
+
 /*****************************************************
  * X11 specific implementations of generic functions *
  *****************************************************/
@@ -780,6 +921,45 @@
 }
 
 static void
+gdk_x11_draw_glyphs (GdkDrawable      *drawable,
+		     GdkGC            *gc,
+		     PangoFont        *font,
+		     gint              x,
+		     gint              y,
+		     PangoGlyphString *glyphs)
+{
+  gdk_x11_draw_glyphs_transformed (drawable, gc, NULL,
+				   font,
+				   x * PANGO_SCALE,
+				   y * PANGO_SCALE,
+				   glyphs);
+}
+
+static void
+gdk_x11_draw_glyphs_transformed (GdkDrawable      *drawable,
+				 GdkGC            *gc,
+				 PangoMatrix      *matrix,
+				 PangoFont        *font,
+				 gint              x,
+				 gint              y,
+				 PangoGlyphString *glyphs)
+{
+  GdkDrawableImplX11 *impl;
+  PangoRenderer *renderer;
+
+  impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+
+  g_return_if_fail (PANGO_XFT_IS_FONT (font));
+
+  renderer = _gdk_x11_renderer_get (drawable, gc);
+  if (matrix)
+    pango_renderer_set_matrix (renderer, matrix);
+  pango_renderer_draw_glyphs (renderer, font, glyphs, x, y);
+  if (matrix)
+    pango_renderer_set_matrix (renderer, NULL);
+}
+
+static void
 gdk_x11_draw_image     (GdkDrawable     *drawable,
                         GdkGC           *gc,
                         GdkImage        *image,
@@ -1444,6 +1624,47 @@
 }
 
 static void
+gdk_x11_draw_trapezoids (GdkDrawable  *drawable,
+			 GdkGC	      *gc,
+			 GdkTrapezoid *trapezoids,
+			 gint          n_trapezoids)
+{
+  GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
+  GdkDisplay *display = gdk_screen_get_display (screen);
+  XTrapezoid *xtrapezoids;
+  gint i;
+
+  if (!_gdk_x11_have_render_with_trapezoids (display))
+    {
+      GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper;
+      GDK_DRAWABLE_CLASS (_gdk_drawable_impl_x11_parent_class)->draw_trapezoids (wrapper, gc,
+							  trapezoids, n_trapezoids);
+      return;
+    }
+
+  xtrapezoids = g_new (XTrapezoid, n_trapezoids);
+
+  for (i = 0; i < n_trapezoids; i++)
+    {
+      xtrapezoids[i].top = XDoubleToFixed (trapezoids[i].y1);
+      xtrapezoids[i].bottom = XDoubleToFixed (trapezoids[i].y2);
+      xtrapezoids[i].left.p1.x = XDoubleToFixed (trapezoids[i].x11);
+      xtrapezoids[i].left.p1.y = XDoubleToFixed (trapezoids[i].y1);
+      xtrapezoids[i].left.p2.x = XDoubleToFixed (trapezoids[i].x12);
+      xtrapezoids[i].left.p2.y = XDoubleToFixed (trapezoids[i].y2);
+      xtrapezoids[i].right.p1.x = XDoubleToFixed (trapezoids[i].x21);
+      xtrapezoids[i].right.p1.y = XDoubleToFixed (trapezoids[i].y1);
+      xtrapezoids[i].right.p2.x = XDoubleToFixed (trapezoids[i].x22);
+      xtrapezoids[i].right.p2.y = XDoubleToFixed (trapezoids[i].y2);
+    }
+
+  _gdk_x11_drawable_draw_xtrapezoids (drawable, gc,
+				      xtrapezoids, n_trapezoids);
+  
+  g_free (xtrapezoids);
+}
+
+static void
 gdk_x11_cairo_surface_destroy (void *data)
 {
   GdkDrawableImplX11 *impl = data;
@@ -1498,5 +1719,89 @@
   return impl->cairo_surface;
 }
 
+void
+_gdk_x11_drawable_draw_xtrapezoids (GdkDrawable      *drawable,
+				    GdkGC            *gc,
+				    XTrapezoid       *xtrapezoids,
+				    int               n_trapezoids)
+{
+  GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
+  GdkDisplay *display = gdk_screen_get_display (screen);
+  GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
+   
+  XftDraw *draw;
+
+  if (!_gdk_x11_have_render_with_trapezoids (display))
+    {
+      /* This is the case of drawing the borders of the unknown glyph box
+       * without render on the display, we need to feed it back to
+       * fallback code. Not efficient, but doesn't matter.
+       */
+      GdkTrapezoid *trapezoids = g_new (GdkTrapezoid, n_trapezoids);
+      int i;
+
+      for (i = 0; i < n_trapezoids; i++)
+	{
+	  trapezoids[i].y1 = XFixedToDouble (xtrapezoids[i].top);
+	  trapezoids[i].y2 = XFixedToDouble (xtrapezoids[i].bottom);
+	  trapezoids[i].x11 = XFixedToDouble (xtrapezoids[i].left.p1.x);
+	  trapezoids[i].x12 = XFixedToDouble (xtrapezoids[i].left.p2.x);
+	  trapezoids[i].x21 = XFixedToDouble (xtrapezoids[i].right.p1.x);
+	  trapezoids[i].x22 = XFixedToDouble (xtrapezoids[i].right.p2.x);
+	}
+
+      gdk_x11_draw_trapezoids (drawable, gc, trapezoids, n_trapezoids);
+      g_free (trapezoids);
+
+      return;
+    }
+
+  gdk_x11_drawable_update_xft_clip (drawable, gc);
+  draw = gdk_x11_drawable_get_xft_draw (drawable);
+
+  if (!x11display->mask_format)
+    x11display->mask_format = XRenderFindStandardFormat (x11display->xdisplay,
+							 PictStandardA8);
+
+  XRenderCompositeTrapezoids (x11display->xdisplay, PictOpOver,
+			      _gdk_x11_gc_get_fg_picture (gc),
+			      XftDrawPicture (draw),
+			      x11display->mask_format,
+			      - gc->ts_x_origin, - gc->ts_y_origin,
+			      xtrapezoids, n_trapezoids);
+}
+
+void
+_gdk_x11_drawable_draw_xft_glyphs (GdkDrawable      *drawable,
+				   GdkGC            *gc,
+				   XftFont          *xft_font,
+				   XftGlyphSpec     *glyphs,
+				   gint              n_glyphs)
+{
+  GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
+  GdkDisplay *display = gdk_screen_get_display (screen);
+  GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
+  XftDraw *draw;
+   
+  gdk_x11_drawable_update_xft_clip (drawable, gc);
+  draw = gdk_x11_drawable_get_xft_draw (drawable);
+
+  if (_gdk_x11_have_render (display))
+    {
+      XftGlyphSpecRender (x11display->xdisplay, PictOpOver,
+			  _gdk_x11_gc_get_fg_picture (gc),
+			  xft_font,
+			  XftDrawPicture (draw),
+			  - gc->ts_x_origin, - gc->ts_y_origin,
+			  glyphs, n_glyphs);
+    }
+  else
+    {
+      XftColor color;
+      
+      _gdk_gc_x11_get_fg_xft_color (gc, &color);
+      XftDrawGlyphSpec (draw, &color, xft_font, glyphs, n_glyphs);
+    }
+}
 #define __GDK_DRAWABLE_X11_C__
 #include "gdkaliasdef.c"
Index: gtk+-2.10.6/gdk/x11/gdkdrawable-x11.h
===================================================================
--- gtk+-2.10.6.orig/gdk/x11/gdkdrawable-x11.h	2006-10-30 12:58:30.000000000 +0000
+++ gtk+-2.10.6/gdk/x11/gdkdrawable-x11.h	2006-10-30 12:59:30.000000000 +0000
@@ -33,6 +33,7 @@
 
 #include <X11/Xlib.h>
 #include <X11/extensions/Xrender.h>
+#include <X11/Xft/Xft.h>
 
 G_BEGIN_DECLS
 
@@ -68,6 +69,8 @@
   Window xid;
   GdkScreen *screen;
 
+  XftDraw *xft_draw;
+	
   Picture picture;
   cairo_surface_t *cairo_surface;
 };
@@ -92,7 +95,15 @@
 /* Note that the following take GdkDrawableImplX11, not the wrapper drawable */
 void _gdk_x11_drawable_finish           (GdkDrawable  *drawable);
 void _gdk_x11_drawable_update_size      (GdkDrawable  *drawable);
-
+void _gdk_x11_drawable_draw_xtrapezoids (GdkDrawable  *drawable,
+					 GdkGC        *gc,
+					 XTrapezoid   *xtrapezoids,
+					 int           n_trapezoids);
+void _gdk_x11_drawable_draw_xft_glyphs  (GdkDrawable  *drawable,
+					 GdkGC        *gc,
+					 XftFont      *xft_font,
+					 XftGlyphSpec *glyphs,
+					 gint          n_glyphs);
 G_END_DECLS
 
 #endif /* __GDK_DRAWABLE_X11_H__ */
Index: gtk+-2.10.6/gdk/x11/gdkgc-x11.c
===================================================================
--- gtk+-2.10.6.orig/gdk/x11/gdkgc-x11.c	2006-10-30 12:58:30.000000000 +0000
+++ gtk+-2.10.6/gdk/x11/gdkgc-x11.c	2006-10-30 12:59:30.000000000 +0000
@@ -80,7 +80,10 @@
 gdk_gc_x11_finalize (GObject *object)
 {
   GdkGCX11 *x11_gc = GDK_GC_X11 (object);
-  
+
+  if (x11_gc->fg_picture != None)
+    XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), x11_gc->fg_picture);
+	
   XFreeGC (GDK_GC_XDISPLAY (x11_gc), GDK_GC_XGC (x11_gc));
 
   G_OBJECT_CLASS (_gdk_gc_x11_parent_class)->finalize (object);
@@ -110,7 +113,7 @@
 
   private->dirty_mask = 0;
   private->have_clip_mask = FALSE;
-    
+	
   private->screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
 
   private->depth = gdk_drawable_get_depth (drawable);
@@ -339,6 +342,18 @@
 }
 
 static void
+clear_fg_picture (GdkGC *gc)
+{
+  GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
+
+  if (x11_gc->fg_picture != None)
+    {
+      XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), x11_gc->fg_picture);
+      x11_gc->fg_picture = None;
+    }
+}
+
+static void
 gdk_x11_gc_set_values (GdkGC           *gc,
 		       GdkGCValues     *values,
 		       GdkGCValuesMask  values_mask)
@@ -367,6 +382,29 @@
       x11_gc->have_clip_mask = values->clip_mask != NULL;
     }
 
+  if (values_mask & GDK_GC_BACKGROUND)
+    {
+      if (_gdk_gc_get_fill (gc) == GDK_OPAQUE_STIPPLED)
+	    clear_fg_picture (gc);
+    }
+
+  if (values_mask & GDK_GC_FILL)
+    {
+      clear_fg_picture (gc);
+    }
+    
+  if (values_mask & GDK_GC_STIPPLE)
+    {
+      if (_gdk_gc_get_fill (gc) == GDK_STIPPLED || _gdk_gc_get_fill (gc) == GDK_OPAQUE_STIPPLED)
+        clear_fg_picture (gc);
+    }
+  
+  if (values_mask & GDK_GC_TILE)
+    {
+      if (_gdk_gc_get_fill (gc) == GDK_TILED)
+	clear_fg_picture (gc);
+    }
+    
   gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask);
 
   XChangeGC (GDK_GC_XDISPLAY (gc),
@@ -642,6 +680,8 @@
   x11_dst_gc->dirty_mask = x11_src_gc->dirty_mask;
   x11_dst_gc->have_clip_region = x11_src_gc->have_clip_region;
   x11_dst_gc->have_clip_mask = x11_src_gc->have_clip_mask;
+    
+  clear_fg_picture (dst_gc);
 }
 
 /**
@@ -701,5 +741,359 @@
   return gc_x11->xgc;
 }
 
+/* Various bits of the below are roughly cribbed from XFree86
+ * lib/Xft/xftdraw.c, Copyright 2000, Keith Packard
+ */
+
+static XRenderPictFormat *
+foreground_format (GdkGC *gc)
+{
+  XRenderPictFormat pf;
+
+  pf.type = PictTypeDirect;
+  pf.depth = 32;
+  pf.direct.redMask = 0xff;
+  pf.direct.greenMask = 0xff;
+  pf.direct.blueMask = 0xff;
+  pf.direct.alphaMask = 0xff;
+
+  return XRenderFindFormat (GDK_GC_XDISPLAY (gc),
+			    (PictFormatType |
+			     PictFormatDepth |
+			     PictFormatRedMask |
+			     PictFormatGreenMask |
+			     PictFormatBlueMask |
+			     PictFormatAlphaMask),
+			    &pf,
+			    0);
+}
+
+static Picture
+make_fg_tile_picture (GdkGC *gc)
+{
+  GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
+  GdkVisual *visual = gdk_drawable_get_visual (_gdk_gc_get_tile (gc));
+  XRenderPictFormat *format = NULL;
+
+  if (visual)
+    {
+      format = XRenderFindVisualFormat (GDK_GC_XDISPLAY (gc),
+					GDK_VISUAL_XVISUAL (visual));
+    }
+  else if (x11_gc->depth == 1)
+    {
+      format = XRenderFindStandardFormat (GDK_GC_XDISPLAY (gc),
+					  PictStandardA1);
+    }
+
+  if (format)
+    {
+      XRenderPictureAttributes pa;
+      pa.repeat = True;
+
+      return XRenderCreatePicture (GDK_GC_XDISPLAY (gc), 
+				   GDK_PIXMAP_XID (_gdk_gc_get_tile (gc)),
+				   format,
+				   CPRepeat, &pa);
+    }
+
+  return None;
+}
+
+static Picture
+make_stipple_picture (GdkGC *gc)
+{
+  XRenderPictFormat *format = NULL;
+  XRenderPictureAttributes pa;
+  
+  format = XRenderFindStandardFormat (GDK_GC_XDISPLAY (gc),
+				      PictStandardA1);
+
+  pa.repeat = True;
+  return XRenderCreatePicture (GDK_GC_XDISPLAY (gc), 
+			       GDK_PIXMAP_XID (_gdk_gc_get_stipple (gc)),
+			       format,
+			       CPRepeat, &pa);
+}
+
+static Picture
+make_color_picture (GdkGC        *gc,
+		    XRenderColor *color)
+{
+  GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
+  XRenderPictureAttributes pa;
+  XRenderPictFormat *pix_format = foreground_format (gc);
+  Pixmap pix;
+  Picture picture;
+  
+  if (!pix_format)
+    return None;
+  
+  pix = XCreatePixmap (GDK_GC_XDISPLAY (gc),
+		       GDK_SCREEN_XROOTWIN (x11_gc->screen),
+		       1, 1, pix_format->depth);
+  pa.repeat = True;
+  picture = XRenderCreatePicture (GDK_GC_XDISPLAY (gc),
+				  pix,
+				  pix_format,
+				  CPRepeat, &pa);
+  XFreePixmap (GDK_GC_XDISPLAY (gc), pix);
+  
+  XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, 
+			picture, color,
+			0, 0, 1, 1);
+
+  return picture;
+}
+
+static void
+get_bg_color (GdkGC        *gc,
+	      XRenderColor *render_color)
+{
+  GdkColormap *cmap;
+  
+  cmap = gdk_gc_get_colormap (gc);
+
+  if (cmap)
+    {
+      GdkColor color;
+      
+      gdk_colormap_query_color (cmap, _gdk_gc_get_bg_pixel (gc), &color);
+      
+      render_color->alpha = 0xffff;
+      render_color->red = color.red;
+      render_color->green = color.green;
+      render_color->blue = color.blue;
+    }
+  else				/* Not worth warning, just use black */
+    {
+      render_color->alpha = 0xffff;
+      render_color->red = 0;
+      render_color->green = 0;
+      render_color->blue = 0;
+    }
+}
+
+/**
+ * _gdk_x11_gc_get_fg_picture:
+ * @gc: a #GdkGC
+ * 
+ * Gets a Xrender Picture object suitable for being the source
+ * drawable for drawing with the foreground the graphics context.
+ * 
+ * Return value: a Picture, owned by the GC; this cannot be
+ *   used over subsequent modification of the GC.
+ **/
+Picture
+_gdk_x11_gc_get_fg_picture (GdkGC *gc)
+{
+  GdkGCX11 *x11_gc;
+  gboolean new = FALSE;
+  XftColor xftcolor;
+  GdkFill fill;
+  int width, height;
+  
+  g_return_val_if_fail (GDK_IS_GC_X11 (gc), None);
+
+  if (!_gdk_x11_have_render (GDK_GC_DISPLAY (gc)))
+    return None;
+
+  x11_gc = GDK_GC_X11 (gc);
+
+  fill = GDK_SOLID;
+  width = 1;
+  height = 1;
+  
+  switch (_gdk_gc_get_fill (gc))
+    {
+    case GDK_SOLID:
+      break;
+    case GDK_TILED:
+      if (_gdk_gc_get_tile (gc))
+	{
+	  if (!x11_gc->fg_picture)
+	    x11_gc->fg_picture = make_fg_tile_picture (gc);
+
+	  if (x11_gc->fg_picture != None)
+	    return x11_gc->fg_picture;
+	}
+      break;
+    case GDK_STIPPLED:
+    case GDK_OPAQUE_STIPPLED:
+      if (_gdk_gc_get_stipple (gc))
+	{
+	  gdk_drawable_get_size (_gdk_gc_get_stipple (gc), &width, &height);
+	  fill = _gdk_gc_get_fill (gc);
+	}
+      break;
+    }
+  
+  if (x11_gc->fg_picture == None)
+    {
+      XRenderPictureAttributes pa;
+      XRenderPictFormat *pix_format = foreground_format (gc);
+      Pixmap pix;
+
+      if (!pix_format)
+	return None;
+
+      pix = XCreatePixmap (GDK_GC_XDISPLAY (gc), 
+			   GDK_SCREEN_XROOTWIN (x11_gc->screen),
+			   width, height, pix_format->depth);
+      pa.repeat = True;
+      x11_gc->fg_picture = XRenderCreatePicture (GDK_GC_XDISPLAY (gc), 
+						 pix,
+						 pix_format,
+						 CPRepeat, &pa);
+      XFreePixmap (GDK_GC_XDISPLAY (gc), pix);
+      
+      new = TRUE;
+    }
+
+  _gdk_gc_x11_get_fg_xft_color (gc, &xftcolor);
+  
+  if (x11_gc->fg_picture_color.alpha != 0xffff ||
+      x11_gc->fg_picture_color.red != xftcolor.color.red ||
+      x11_gc->fg_picture_color.green != xftcolor.color.green ||
+      x11_gc->fg_picture_color.blue != xftcolor.color.blue)
+    {
+      x11_gc->fg_picture_color.alpha = 0xffff;
+      x11_gc->fg_picture_color.red = xftcolor.color.red;
+      x11_gc->fg_picture_color.green = xftcolor.color.green;
+      x11_gc->fg_picture_color.blue = xftcolor.color.blue;
+
+      new = TRUE;
+    }
+
+  switch (fill)
+    {
+    case GDK_SOLID:
+      XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, 
+			    x11_gc->fg_picture, &x11_gc->fg_picture_color,
+			    0, 0, width, height);
+      break;
+    case GDK_STIPPLED:
+      {
+	Picture stipple_picture = make_stipple_picture (gc);
+	
+	XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, 
+			      x11_gc->fg_picture, &x11_gc->fg_picture_color,
+			      0, 0, width, height);
+	XRenderComposite (GDK_GC_XDISPLAY (gc),
+			  PictOpInReverse,
+			  stipple_picture, None, x11_gc->fg_picture,
+			  0, 0, 0, 0, 0, 0, width, height);
+	
+	XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), stipple_picture);
+      }
+      break;
+    case GDK_OPAQUE_STIPPLED:
+      {
+	XRenderColor bg_color;
+
+	Picture stipple_picture = make_stipple_picture (gc);
+	Picture fg_picture = make_color_picture (gc, &x11_gc->fg_picture_color);
+
+	get_bg_color (gc, &bg_color);
+	
+	XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, 
+			      x11_gc->fg_picture, &bg_color,
+			      0, 0, width, height);
+	XRenderComposite (GDK_GC_XDISPLAY (gc),
+			  PictOpOver,
+			  fg_picture, stipple_picture, x11_gc->fg_picture,
+			  0, 0, 0, 0, 0, 0, width, height);
+
+	XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), stipple_picture);
+	XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), fg_picture);
+      }
+      break;
+    case GDK_TILED:
+      g_assert_not_reached ();	/* handled above */
+      break;
+    }
+
+  return x11_gc->fg_picture;
+}
+
+/**
+ * _gdk_gc_x11_get_fg_xft_color:
+ * @gc: a #GdkGC
+ * @xftcolor: location to store the color
+ * 
+ * Gets the foreground color of the GC as a XftColor.
+ **/
+void
+_gdk_gc_x11_get_fg_xft_color (GdkGC    *gc,
+			      XftColor *xftcolor)
+{
+  GdkGCX11 *x11_gc;
+  GdkColormap *cmap;
+  GdkColor color;
+  
+  g_return_if_fail (GDK_IS_GC_X11 (gc));
+
+  x11_gc = GDK_GC_X11 (gc);
+
+  cmap = gdk_gc_get_colormap (gc);
+
+  xftcolor->pixel = _gdk_gc_get_fg_pixel (gc);
+
+  if (cmap)
+    {
+      gdk_colormap_query_color (cmap, xftcolor->pixel, &color);
+      xftcolor->color.alpha = 0xffff;
+      xftcolor->color.red = color.red;
+      xftcolor->color.green = color.green;
+      xftcolor->color.blue = color.blue;
+    }
+  else if (x11_gc->depth == 1)
+    {
+      /* Drawing with Xft on a bitmap is a bit bizzare; it
+       * takes alpha >= 0x8000 to mean 'set to 1' and
+       * alpha < 0x8000 to mean 'set to 0'.
+       */
+      if (xftcolor->pixel)
+        {
+	  xftcolor->color.red = 0xffff;
+	  xftcolor->color.green = 0xffff;
+	  xftcolor->color.blue = 0xffff;
+	  xftcolor->color.alpha = 0xffff;
+	}
+      else
+        {
+	  xftcolor->color.red = 0;
+	  xftcolor->color.green = 0;
+	  xftcolor->color.blue = 0;
+	  xftcolor->color.alpha = 0;
+	}
+    }
+  else
+    {
+      g_warning ("Using Xft rendering requires the GC argument to have a\n"
+		 "specified colormap. If the GC was created for a drawable\n"
+		 "with a colormap, the colormap will be set on the GC\n"
+		 "automatically. Otherwise, a colormap must be set on it with"
+		 "gdk_gc_set_colormap");
+    }
+}
+
+void
+_gdk_windowing_gc_get_foreground (GdkGC    *gc,
+				  GdkColor *color)
+{
+  GdkColormap *cmap;
+  
+  g_return_if_fail (GDK_IS_GC_X11 (gc));
+
+  color->pixel = _gdk_gc_get_fg_pixel (gc);
+
+  cmap = gdk_gc_get_colormap (gc);
+
+  if (cmap)
+    gdk_colormap_query_color (cmap, _gdk_gc_get_fg_pixel (gc), color);
+  else
+    g_warning ("No colormap in _gdk_windowing_gc_get_foreground");
+}
 #define __GDK_GC_X11_C__
 #include "gdkaliasdef.c"
Index: gtk+-2.10.6/gdk/x11/gdkprivate-x11.h
===================================================================
--- gtk+-2.10.6.orig/gdk/x11/gdkprivate-x11.h	2006-10-30 12:58:30.000000000 +0000
+++ gtk+-2.10.6/gdk/x11/gdkprivate-x11.h	2006-10-30 12:59:30.000000000 +0000
@@ -63,6 +63,9 @@
   guint have_clip_region : 1;
   guint have_clip_mask : 1;
   guint depth : 8;
+    
+  Picture fg_picture;
+  XRenderColor fg_picture_color; 
 };
 
 struct _GdkGCX11Class
@@ -102,6 +105,11 @@
 GType _gdk_gc_x11_get_type (void);
 
 gboolean _gdk_x11_have_render           (GdkDisplay *display);
+gboolean _gdk_x11_have_render_with_trapezoids (GdkDisplay *display);
+
+Picture  _gdk_x11_gc_get_fg_picture   (GdkGC      *gc);
+void     _gdk_gc_x11_get_fg_xft_color (GdkGC      *gc,
+				       XftColor   *xftcolor);
 
 GdkGC *_gdk_x11_gc_new                  (GdkDrawable     *drawable,
 					 GdkGCValues     *values,
Index: gtk+-2.10.6/gdk/x11/gdkwindow-x11.c
===================================================================
--- gtk+-2.10.6.orig/gdk/x11/gdkwindow-x11.c	2006-10-30 12:58:30.000000000 +0000
+++ gtk+-2.10.6/gdk/x11/gdkwindow-x11.c	2006-10-30 12:59:30.000000000 +0000
@@ -1114,7 +1114,8 @@
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkToplevelX11 *toplevel;
-  
+  GdkDrawableImplX11 *draw_impl;
+	
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   _gdk_selection_window_destroyed (window);
@@ -1126,6 +1127,11 @@
   if (toplevel)
     gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
 
+  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
+    
+  if (draw_impl->xft_draw)
+    XftDrawDestroy (draw_impl->xft_draw);
+  
   _gdk_x11_drawable_finish (private->impl);
 
   if (!recursing && !foreign_destroy)
Index: gtk+-2.10.6/gdk/x11/Makefile.am
===================================================================
--- gtk+-2.10.6.orig/gdk/x11/Makefile.am	2006-10-30 12:58:30.000000000 +0000
+++ gtk+-2.10.6/gdk/x11/Makefile.am	2006-10-30 12:59:30.000000000 +0000
@@ -37,6 +37,7 @@
 	gdkinput.c	   	\
 	gdkkeys-x11.c		\
 	gdkmain-x11.c	   	\
+	gdkpango-x11.c		\
 	gdkpixmap-x11.c	   	\
 	gdkpixmap-x11.h		\
 	gdkproperty-x11.c  	\
Index: gtk+-2.10.6/gtk/gtkcalendar.c
===================================================================
--- gtk+-2.10.6.orig/gtk/gtkcalendar.c	2006-10-30 12:58:30.000000000 +0000
+++ gtk+-2.10.6/gtk/gtkcalendar.c	2006-10-30 12:59:30.000000000 +0000
@@ -1821,7 +1821,7 @@
     }
 }
 
-
+
 /****************************************
  *              Repainting              *
  ****************************************/
@@ -1831,7 +1831,7 @@
 {
   GtkWidget *widget = GTK_WIDGET (calendar);
   GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
-  cairo_t *cr;
+  GdkGC *gc;
   char buffer[255];
   int x, y;
   gint header_width;
@@ -1849,7 +1849,7 @@
   else
     year_left = !priv->year_before;
 
-  cr = gdk_cairo_create (priv->header_win);
+  gc = calendar->gc;
   
   header_width = widget->allocation.width - 2 * widget->style->xthickness;
   
@@ -1902,9 +1902,9 @@
 			  - (max_year_width - logical_rect.width)/2);
   
 
-  gdk_cairo_set_source_color (cr, HEADER_FG_COLOR (GTK_WIDGET (calendar)));
-  cairo_move_to (cr, x, y);
-  pango_cairo_show_layout (cr, layout);
+  gdk_gc_set_foreground (gc, HEADER_FG_COLOR (GTK_WIDGET (calendar)));
+  gdk_draw_layout (priv->header_win, gc, x, y, layout);
+  
   
   /* Draw month */
   g_snprintf (buffer, sizeof (buffer), "%s", default_monthname[calendar->month]);
@@ -1924,19 +1924,19 @@
     else
     x = 3 + priv->arrow_width + (max_month_width - logical_rect.width)/2;
 
-  cairo_move_to (cr, x, y);
-  pango_cairo_show_layout (cr, layout);
-
+  gdk_draw_layout (priv->header_win, gc, x, y, layout);
+  
+  gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar)));
+  
   g_object_unref (layout);
-  cairo_destroy (cr);
 }
 
 static void
 calendar_paint_day_names (GtkCalendar *calendar)
 {
   GtkWidget *widget = GTK_WIDGET (calendar);
+  GdkGC *gc;
   GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
-  cairo_t *cr;
   char buffer[255];
   int day,i;
   int day_width, cal_width;
@@ -1946,8 +1946,7 @@
   gint focus_padding;
   gint focus_width;
   
-  cr = gdk_cairo_create (priv->day_name_win);
-  
+  gc = calendar->gc;
   gtk_widget_style_get (GTK_WIDGET (widget),
 			"focus-line-width", &focus_width,
 			"focus-padding", &focus_padding,
@@ -1961,22 +1960,19 @@
    * Draw rectangles as inverted background for the labels.
    */
 
-  gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget));
-  cairo_rectangle (cr,
-		   CALENDAR_MARGIN, CALENDAR_MARGIN,
-		   cal_width-CALENDAR_MARGIN * 2,
-		   priv->day_name_h - CALENDAR_MARGIN);
-  cairo_fill (cr);
-  
+  gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (widget));
+  gdk_draw_rectangle (priv->day_name_win, gc, TRUE,
+		      CALENDAR_MARGIN, CALENDAR_MARGIN,
+		      cal_width-CALENDAR_MARGIN * 2,
+		      priv->day_name_h - CALENDAR_MARGIN);
+    
   if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
-    {
-      cairo_rectangle (cr, 
-		       CALENDAR_MARGIN,
-		       priv->day_name_h - CALENDAR_YSEP,
-		       priv->week_width - CALENDAR_YSEP - CALENDAR_MARGIN,
-		       CALENDAR_YSEP);
-      cairo_fill (cr);
-    }
+    gdk_draw_rectangle (priv->day_name_win, gc, TRUE,
+			CALENDAR_MARGIN,
+			priv->day_name_h - CALENDAR_YSEP,
+			priv->week_width - CALENDAR_YSEP - CALENDAR_MARGIN,
+			CALENDAR_YSEP);
+  
   
   /*
    * Write the labels
@@ -1984,7 +1980,7 @@
 
   layout = gtk_widget_create_pango_layout (widget, NULL);
 
-  gdk_cairo_set_source_color (cr, SELECTED_FG_COLOR (widget));
+  gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget));
   for (i = 0; i < 7; i++)
     {
       if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL)
@@ -1997,19 +1993,18 @@
       pango_layout_set_text (layout, buffer, -1);
       pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
 
-      cairo_move_to (cr, 
-		     (CALENDAR_MARGIN +
-		      + (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ?
-			 (priv->week_width + (priv->week_width ? CALENDAR_XSEP : 0))
-			 : 0)
-		      + day_wid_sep * i
-		      + (day_width - logical_rect.width)/2),
-		     CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y);
-      pango_cairo_show_layout (cr, layout);
+      gdk_draw_layout (priv->day_name_win, gc, 
+		       (CALENDAR_MARGIN +
+			+ (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ?
+			   (priv->week_width + (priv->week_width ? CALENDAR_XSEP : 0))
+			   : 0)
+			+ day_wid_sep * i
+			+ (day_width - logical_rect.width)/2),
+		       CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y,
+		       layout);
     }
   
   g_object_unref (layout);
-  cairo_destroy (cr);
 }
 
 static void
@@ -2017,7 +2012,7 @@
 {
   GtkWidget *widget = GTK_WIDGET (calendar);
   GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
-  cairo_t *cr;
+  GdkGC *gc;
   gint row, week = 0, year;
   gint x_loc;
   char buffer[32];
@@ -2027,7 +2022,7 @@
   gint focus_padding;
   gint focus_width;
   
-  cr = gdk_cairo_create (priv->week_win);
+  gc = calendar->gc;
   
   gtk_widget_style_get (GTK_WIDGET (widget),
 			"focus-line-width", &focus_width,
@@ -2038,20 +2033,20 @@
    * Draw a rectangle as inverted background for the labels.
    */
 
-  gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget));
+  gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (widget));
   if (priv->day_name_win)
-    cairo_rectangle (cr, 
-		     CALENDAR_MARGIN,
-		     0,
-		     priv->week_width - CALENDAR_MARGIN,
-		     priv->main_h - CALENDAR_MARGIN);
+    gdk_draw_rectangle (priv->week_win, gc, TRUE,
+			CALENDAR_MARGIN,
+			0,
+			priv->week_width - CALENDAR_MARGIN,
+			priv->main_h - CALENDAR_MARGIN);
   else
-    cairo_rectangle (cr,
-		     CALENDAR_MARGIN,
-		     CALENDAR_MARGIN,
-		     priv->week_width - CALENDAR_MARGIN,
-		     priv->main_h - 2 * CALENDAR_MARGIN);
-  cairo_fill (cr);
+    gdk_draw_rectangle (priv->week_win, gc, TRUE,
+			CALENDAR_MARGIN,
+			CALENDAR_MARGIN,
+			priv->week_width - CALENDAR_MARGIN,
+			priv->main_h - 2 * CALENDAR_MARGIN);
+  
   
   /*
    * Write the labels
@@ -2059,7 +2054,7 @@
   
   layout = gtk_widget_create_pango_layout (widget, NULL);
   
-  gdk_cairo_set_source_color (cr, SELECTED_FG_COLOR (widget));
+  gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget));
   day_height = calendar_row_height (calendar);
   for (row = 0; row < 6; row++)
     {
@@ -2095,12 +2090,10 @@
 	       - logical_rect.width
 	       - CALENDAR_XSEP - focus_padding - focus_width);
 
-      cairo_move_to (cr, x_loc, y_loc);
-      pango_cairo_show_layout (cr, layout);
+      gdk_draw_layout (priv->week_win, gc, x_loc, y_loc, layout);
     }
   
   g_object_unref (layout);
-  cairo_destroy (cr);
 }
 
 static void
@@ -2149,7 +2142,7 @@
 {
   GtkWidget *widget = GTK_WIDGET (calendar);
   GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
-  cairo_t *cr;
+  GdkGC *gc;
   GdkColor *text_color;
   gchar buffer[32];
   gint day;
@@ -2162,7 +2155,7 @@
   g_return_if_fail (row < 6);
   g_return_if_fail (col < 7);
 
-  cr = gdk_cairo_create (priv->main_win);
+  gc = calendar->gc;
 
   day = calendar->day[row][col];
 
@@ -2170,11 +2163,11 @@
   
   if (calendar->day_month[row][col] == MONTH_PREV)
     {
-      text_color = PREV_MONTH_COLOR (widget);
+      gdk_gc_set_foreground (gc, PREV_MONTH_COLOR (GTK_WIDGET (calendar)));
     } 
   else if (calendar->day_month[row][col] == MONTH_NEXT)
     {
-      text_color =  NEXT_MONTH_COLOR (widget);
+      gdk_gc_set_foreground (gc, NEXT_MONTH_COLOR (GTK_WIDGET (calendar)));
     } 
   else 
     {
@@ -2188,16 +2181,16 @@
 #endif     
       if (calendar->selected_day == day)
 	{
-	  gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget));
-	  gdk_cairo_rectangle (cr, &day_rect);
-	  cairo_fill (cr);
+	  gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (GTK_WIDGET (calendar)));
+	  gdk_draw_rectangle (priv->main_win, gc, TRUE, day_rect.x, day_rect.y,
+			      day_rect.width, day_rect.height);
 	}
       if (calendar->selected_day == day)
-	text_color = SELECTED_FG_COLOR (widget);
+	gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (GTK_WIDGET (calendar)));
       else if (calendar->marked_date[day-1])
-	text_color = MARKED_COLOR (widget);
+	gdk_gc_set_foreground (gc, MARKED_COLOR	 (GTK_WIDGET (calendar)));
       else
-	text_color = NORMAL_DAY_COLOR (widget);
+	gdk_gc_set_foreground (gc, NORMAL_DAY_COLOR (GTK_WIDGET (calendar)));
     }
 
   /* Translators: this defines whether the day numbers should use
@@ -2219,16 +2212,13 @@
   x_loc -= logical_rect.width;
   y_loc = day_rect.y + (day_rect.height - logical_rect.height) / 2;
   
-  gdk_cairo_set_source_color (cr, text_color);
-  cairo_move_to (cr, x_loc, y_loc);
-  pango_cairo_show_layout (cr, layout);
+  gdk_draw_layout (priv->main_win, gc,
+		   x_loc, y_loc, layout);
     
   if (calendar->marked_date[day-1]
       && calendar->day_month[row][col] == MONTH_CURRENT)
-    {
-      cairo_move_to (cr, x_loc - 1, y_loc);
-      pango_cairo_show_layout (cr, layout);
-    }
+    gdk_draw_layout (priv->main_win, gc,
+		     x_loc-1, y_loc, layout);
 
   if (GTK_WIDGET_HAS_FOCUS (calendar) 
       && calendar->focus_row == row && calendar->focus_col == col)
@@ -2253,7 +2243,6 @@
     }
 
   g_object_unref (layout);
-  cairo_destroy (cr);
 }
 
 static void
Index: gtk+-2.10.6/gtk/gtkentry.c
===================================================================
--- gtk+-2.10.6.orig/gtk/gtkentry.c	2006-10-30 12:58:30.000000000 +0000
+++ gtk+-2.10.6/gtk/gtkentry.c	2006-10-30 12:59:30.000000000 +0000
@@ -3333,7 +3333,6 @@
   if (GTK_WIDGET_DRAWABLE (entry))
     {
       PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
-      cairo_t *cr;
       gint x, y;
       gint start_pos, end_pos;
       
@@ -3341,56 +3340,60 @@
       
       get_layout_position (entry, &x, &y);
 
-      cr = gdk_cairo_create (entry->text_area);
-
-      cairo_move_to (cr, x, y);
-      gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]);
-      pango_cairo_show_layout (cr, layout);
-
+      gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state],       
+                       x, y,
+		       layout);
+        
       if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos))
 	{
 	  gint *ranges;
 	  gint n_ranges, i;
           PangoRectangle logical_rect;
-	  GdkColor *selection_color, *text_color;
+	  GdkGC *selection_gc, *text_gc;
           GtkBorder inner_border;
-
+          GdkRegion *clip_region;
+            
 	  pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
 	  gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
 
 	  if (GTK_WIDGET_HAS_FOCUS (entry))
 	    {
-	      selection_color = &widget->style->base [GTK_STATE_SELECTED];
-	      text_color = &widget->style->text [GTK_STATE_SELECTED];
+	      selection_gc = widget->style->base_gc [GTK_STATE_SELECTED];
+	      text_gc = widget->style->text_gc [GTK_STATE_SELECTED];
 	    }
 	  else
 	    {
-	      selection_color = &widget->style->base [GTK_STATE_ACTIVE];
-	      text_color = &widget->style->text [GTK_STATE_ACTIVE];
+	      selection_gc = widget->style->base_gc [GTK_STATE_ACTIVE];
+	      text_gc = widget->style->text_gc [GTK_STATE_ACTIVE];
 	    }
-
+          
+          clip_region = gdk_region_new ();
           _gtk_entry_effective_inner_border (entry, &inner_border);
 
 	  for (i = 0; i < n_ranges; ++i)
-	    cairo_rectangle (cr,
-			     inner_border.left - entry->scroll_offset + ranges[2 * i],
-			     y,
-			     ranges[2 * i + 1],
-			     logical_rect.height);
+	    {
+	      GdkRectangle rect;
 
-	  cairo_clip (cr);
-	  
-	  gdk_cairo_set_source_color (cr, selection_color);
-	  cairo_paint (cr);
+	      rect.x = inner_border.left - entry->scroll_offset + ranges[2 * i];
+	      rect.y = y;
+	      rect.width = ranges[2 * i + 1];
+	      rect.height = logical_rect.height;
+		
+	      gdk_draw_rectangle (entry->text_area, selection_gc, TRUE,
+				  rect.x, rect.y, rect.width, rect.height);
 
-	  cairo_move_to (cr, x, y);
-	  gdk_cairo_set_source_color (cr, text_color);
-	  pango_cairo_show_layout (cr, layout);
+	      gdk_region_union_with_rect (clip_region, &rect);
+	    }
 	  
+	  gdk_gc_set_clip_region (text_gc, clip_region);
+	  gdk_draw_layout (entry->text_area, text_gc, 
+			   x, y,
+			   layout);
+	  gdk_gc_set_clip_region (text_gc, NULL);
+	  
+	  gdk_region_destroy (clip_region);
 	  g_free (ranges);
 	}
-
-      cairo_destroy (cr);
     }
 }
 
Index: gtk+-2.10.6/gtk/gtkwidget.c
===================================================================
--- gtk+-2.10.6.orig/gtk/gtkwidget.c	2006-10-30 12:58:30.000000000 +0000
+++ gtk+-2.10.6/gtk/gtkwidget.c	2006-10-30 12:59:30.000000000 +0000
@@ -5445,7 +5445,8 @@
       GdkScreen *screen;
 
       update_pango_context (widget, context);
-
+/* TODO: Figure out the proper way to handle this in a pangoxft setting
+        
       screen = gtk_widget_get_screen_unchecked (widget);
       if (screen)
 	{
@@ -5453,7 +5454,7 @@
 					      gdk_screen_get_resolution (screen));
 	  pango_cairo_context_set_font_options (context,
 						gdk_screen_get_font_options (screen));
-	}
+	}*/
     }
 }
 
Index: gtk+-2.10.6/gdk/x11/gdkpango-x11.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gtk+-2.10.6/gdk/x11/gdkpango-x11.c	2006-10-30 12:59:30.000000000 +0000
@@ -0,0 +1,174 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2000 Red Hat, Inc. 
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+
+#include "gdkx.h"
+#include "gdkdisplay-x11.h"
+#include "gdkpango.h"
+#include <pango/pangoxft.h>
+#include <pango/pangoxft-render.h>
+#include "gdkalias.h"
+
+#include <math.h>
+
+typedef struct _GdkX11Renderer      GdkX11Renderer;
+typedef struct _GdkX11RendererClass GdkX11RendererClass;
+
+#define GDK_TYPE_X11_RENDERER            (_gdk_x11_renderer_get_type())
+#define GDK_X11_RENDERER(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_X11_RENDERER, GdkX11Renderer))
+#define GDK_IS_X11_RENDERER(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_X11_RENDERER))
+#define GDK_X11_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_X11_RENDERER, GdkX11RendererClass))
+#define GDK_IS_X11_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_X11_RENDERER))
+#define GDK_X11_RENDERER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_X11_RENDERER, GdkX11RendererClass))
+
+#define MAX_RENDER_PART  PANGO_RENDER_PART_STRIKETHROUGH
+
+struct _GdkX11Renderer
+{
+  PangoXftRenderer parent_instance;
+
+  XRenderPictFormat *mask_format;
+  
+  GdkDrawable *drawable;
+  GdkGC *gc;
+};
+
+struct _GdkX11RendererClass
+{
+  PangoXftRendererClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkX11Renderer, _gdk_x11_renderer, PANGO_TYPE_XFT_RENDERER)
+
+static void
+gdk_x11_renderer_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (_gdk_x11_renderer_parent_class)->finalize (object);
+}
+     
+static void
+gdk_x11_renderer_composite_trapezoids (PangoXftRenderer *xftrenderer,
+				       PangoRenderPart   part,
+				       XTrapezoid       *trapezoids,
+				       int               n_trapezoids)
+{
+  /* Because we only use this renderer for "draw_glyphs()" calls, we
+   * won't hit this code path much. However, it is hit for drawing
+   * the "unknown glyph" hex squares. We can safely ignore the part,
+   */
+  GdkX11Renderer *x11_renderer = GDK_X11_RENDERER (xftrenderer);
+
+  _gdk_x11_drawable_draw_xtrapezoids (x11_renderer->drawable,
+				      x11_renderer->gc,
+				      trapezoids, n_trapezoids);
+
+}
+
+static void
+gdk_x11_renderer_composite_glyphs (PangoXftRenderer *xftrenderer,
+				   XftFont          *xft_font,
+				   XftGlyphSpec     *glyphs,
+				   gint              n_glyphs)
+{
+  GdkX11Renderer *x11_renderer = GDK_X11_RENDERER (xftrenderer);
+
+  _gdk_x11_drawable_draw_xft_glyphs (x11_renderer->drawable,
+				     x11_renderer->gc,
+				     xft_font, glyphs, n_glyphs);
+}
+
+static void
+_gdk_x11_renderer_init (GdkX11Renderer *renderer)
+{
+}
+
+static void
+_gdk_x11_renderer_class_init (GdkX11RendererClass *klass)
+{
+  PangoXftRendererClass *xftrenderer_class = PANGO_XFT_RENDERER_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  
+  xftrenderer_class->composite_glyphs = gdk_x11_renderer_composite_glyphs;
+  xftrenderer_class->composite_trapezoids = gdk_x11_renderer_composite_trapezoids;
+
+  object_class->finalize = gdk_x11_renderer_finalize;
+}
+
+PangoRenderer *
+_gdk_x11_renderer_get (GdkDrawable *drawable,
+		       GdkGC       *gc)
+{
+  GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
+  GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
+  GdkX11Renderer *x11_renderer;
+
+  if (!screen_x11->renderer)
+    {
+      screen_x11->renderer = g_object_new (GDK_TYPE_X11_RENDERER,
+					   "display", GDK_SCREEN_XDISPLAY (screen),
+					   "screen",  GDK_SCREEN_XNUMBER (screen),
+					   NULL);
+    }
+
+  x11_renderer = GDK_X11_RENDERER (screen_x11->renderer);
+
+  x11_renderer->drawable = drawable;
+  x11_renderer->gc = gc;
+
+  return screen_x11->renderer;
+}
+
+/**
+ * gdk_pango_context_get_for_screen:
+ * @screen: the #GdkScreen for which the context is to be created.
+ * 
+ * Creates a #PangoContext for @screen.
+ *
+ * The context must be freed when you're finished with it.
+ * 
+ * When using GTK+, normally you should use gtk_widget_get_pango_context()
+ * instead of this function, to get the appropriate context for
+ * the widget you intend to render text onto.
+ * 
+ * Return value: a new #PangoContext for @screen
+ *
+ * Since: 2.2
+ **/
+PangoContext *
+gdk_pango_context_get_for_screen (GdkScreen *screen)
+{
+  PangoContext *context;
+  
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  if (screen->closed)
+    return NULL;
+  
+  context = pango_xft_get_context (GDK_SCREEN_XDISPLAY (screen),
+				   GDK_SCREEN_X11 (screen)->screen_num);
+  
+  g_object_set_data (G_OBJECT (context), "gdk-pango-screen", screen);
+  
+  return context;
+}
+
+#define __GDK_PANGO_X11_C__
+#include "gdkaliasdef.c"
Index: gtk+-2.10.6/gdk/x11/gdkpixmap-x11.c
===================================================================
--- gtk+-2.10.6.orig/gdk/x11/gdkpixmap-x11.c	2006-10-30 12:58:30.000000000 +0000
+++ gtk+-2.10.6/gdk/x11/gdkpixmap-x11.c	2006-10-30 12:59:30.000000000 +0000
@@ -119,6 +119,9 @@
     {
       GdkDrawableImplX11 *draw_impl = GDK_DRAWABLE_IMPL_X11 (impl);
 
+      if (draw_impl->xft_draw)
+       XftDrawDestroy (draw_impl->xft_draw);
+
       _gdk_x11_drawable_finish (GDK_DRAWABLE (draw_impl));
     }
 
--- gtk+-2.10.6.orig/gtk/gtkcalendar.c.orig	2006-11-14 14:39:34.000000000 -0800
+++ gtk+-2.10.6/gtk/gtkcalendar.c	2006-11-14 14:37:34.000000000 -0800
@@ -1495,6 +1495,10 @@ gtk_calendar_realize (GtkWidget *widget)
 			     BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
   gdk_window_show (priv->main_win);
   gdk_window_set_user_data (priv->main_win, widget);
+
+  /* Set widgets gc */
+  calendar->gc = gdk_gc_new (widget->window);
+
   gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget));
   gdk_window_show (widget->window);
   gdk_window_set_user_data (widget->window, widget);