Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.8351
diff -u -p -r1.8351 ChangeLog
--- ChangeLog	13 Sep 2006 17:23:11 -0000	1.8351
+++ ChangeLog	14 Sep 2006 01:28:39 -0000
@@ -1,3 +1,8 @@
+2006-09-13  Ryan Lortie  <desrt@desrt.ca>
+
+	* gdk/gdkpango.h:
+	* gdk/gdkpango.c: Bug 355343.  Add a GdkPangoAttrDropshadow.
+
 2006-09-13 Matthias Clasen <mclasen@redhat.com>
 
 	* gtk/gtkcolorsel.c: Use a GtkWindow instead of a GtkInvisible
Index: gdk/gdkpango.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkpango.c,v
retrieving revision 1.58
diff -u -p -r1.58 gdkpango.c
--- gdk/gdkpango.c	10 Sep 2006 06:39:14 -0000	1.58
+++ gdk/gdkpango.c	14 Sep 2006 01:28:42 -0000
@@ -49,6 +49,7 @@ struct _GdkPangoRendererPrivate
   
   GdkBitmap *stipple[MAX_RENDER_PART + 1];
   gboolean embossed;
+  gboolean dropshadow;
 
   cairo_t *cr;
   PangoRenderPart last_part;
@@ -62,6 +63,7 @@ struct _GdkPangoRendererPrivate
 
 static PangoAttrType gdk_pango_attr_stipple_type;
 static PangoAttrType gdk_pango_attr_embossed_type;
+static PangoAttrType gdk_pango_attr_dropshadow_type;
 
 enum {
   PROP_0,
@@ -131,6 +133,25 @@ emboss_context (cairo_t *cr)
   cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
 }
 
+/* Adjusts matrix and color for the renderer to draw the secondary
+ * "shadow" copy for embossed text */
+static void
+dropshadow_context_black (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, 0.0, 0.0, 0.0);
+}
+
 static inline gboolean
 color_equal (PangoColor *c1, PangoColor *c2)
 {
@@ -238,9 +259,23 @@ gdk_pango_renderer_draw_glyphs (PangoRen
       pango_cairo_show_glyph_string (cr, font, glyphs);
       cairo_restore (cr);
     }
-  
+
+  if (priv->dropshadow)
+    {
+      cairo_save (cr);
+      dropshadow_context_black (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_save (cr);
+      cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+    }
+
   cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
   pango_cairo_show_glyph_string (cr, font, glyphs);
+
+  if (priv->dropshadow)
+    cairo_restore (cr);
 }
 
 /* Draws an error underline that looks like one of:
@@ -348,10 +383,27 @@ gdk_pango_renderer_draw_rectangle (Pango
       cairo_restore (cr);
     }
 
+  if (priv->dropshadow && part != PANGO_RENDER_PART_BACKGROUND)
+    {
+      cairo_save (cr);
+      dropshadow_context_black (cr);
+      cairo_rectangle (cr,
+		       (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
+		       (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
+
+      cairo_fill (cr);
+      cairo_restore (cr);
+      cairo_save (cr);
+      cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+    }
+
   cairo_rectangle (cr,
 		   (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
 		   (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
   cairo_fill (cr);
+
+  if (priv->dropshadow)
+    cairo_restore (cr);
 }
 
 static void
@@ -377,9 +429,25 @@ gdk_pango_renderer_draw_error_underline 
       cairo_restore (cr);
     }
 
+  if (priv->dropshadow)
+    {
+      cairo_save (cr);
+      dropshadow_context_black (cr);
+      draw_error_underline (cr,
+			    (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
+			    (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
+      cairo_restore (cr);
+      cairo_save (cr);
+      cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+    }
+
+
   draw_error_underline (cr,
 			(double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
 			(double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
+
+  if (priv->dropshadow)
+    cairo_restore (cr);
 }
 
 static void
@@ -424,8 +492,10 @@ gdk_pango_renderer_prepare_run (PangoRen
 				PangoLayoutRun *run)
 {
   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
+  gboolean dropshadow = FALSE;
   gboolean embossed = FALSE;
   GdkBitmap *stipple = NULL;
+  gboolean changed = FALSE;
   GSList *l;
   int i;
   
@@ -448,6 +518,10 @@ gdk_pango_renderer_prepare_run (PangoRen
 	{
 	  embossed = ((GdkPangoAttrEmbossed*)attr)->embossed;
 	}
+      else if (attr->klass->type == gdk_pango_attr_dropshadow_type)
+        {
+          dropshadow = ((GdkPangoAttrDropshadow*)attr)->dropshadow;
+        }
     }
 
   gdk_pango_renderer_set_stipple (gdk_renderer, PANGO_RENDER_PART_FOREGROUND, stipple);
@@ -458,9 +532,18 @@ gdk_pango_renderer_prepare_run (PangoRen
   if (embossed != gdk_renderer->priv->embossed)
     {
       gdk_renderer->priv->embossed = embossed;
-      pango_renderer_part_changed (renderer, PANGO_RENDER_PART_FOREGROUND);
+      changed = TRUE;
+    }
+
+  if (dropshadow != gdk_renderer->priv->dropshadow)
+    {
+      gdk_renderer->priv->dropshadow = dropshadow;
+      changed = TRUE;
     }
 
+  if (changed)
+    pango_renderer_part_changed (renderer, PANGO_RENDER_PART_FOREGROUND);
+
   PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->prepare_run (renderer, run);
 
   for (i = 0; i <= MAX_RENDER_PART; i++)
@@ -1183,10 +1266,9 @@ gdk_pango_attr_embossed_compare (const P
 
 /**
  * gdk_pango_attr_embossed_new:
- * @embossed: a bitmap to be set as embossed
+ * @embossed: if the region should be embossed
  *
- * Creates a new attribute containing a embossed bitmap to be used when
- * rendering the text.
+ * Creates a new attribute flagging a region as embossed or not.
  *
  * Return value: new #PangoAttribute
  **/
@@ -1210,6 +1292,63 @@ gdk_pango_attr_embossed_new (gboolean em
   result = g_new (GdkPangoAttrEmbossed, 1);
   result->attr.klass = &klass;
   result->embossed = embossed;
+  
+  return (PangoAttribute *)result;
+}
+
+static PangoAttribute *
+gdk_pango_attr_dropshadow_copy (const PangoAttribute *attr)
+{
+  const GdkPangoAttrDropshadow *e = (const GdkPangoAttrDropshadow*) attr;
+
+  return gdk_pango_attr_dropshadow_new (e->dropshadow);
+}
+
+static void
+gdk_pango_attr_dropshadow_destroy (PangoAttribute *attr)
+{
+  g_free (attr);
+}
+
+static gboolean
+gdk_pango_attr_dropshadow_compare (const PangoAttribute *attr1,
+                                 const PangoAttribute *attr2)
+{
+  const GdkPangoAttrDropshadow *e1 = (const GdkPangoAttrDropshadow*) attr1;
+  const GdkPangoAttrDropshadow *e2 = (const GdkPangoAttrDropshadow*) attr2;
+
+  return e1->dropshadow == e2->dropshadow;
+}
+
+/**
+ * gdk_pango_attr_dropshadow_new:
+ * @dropshadow: if the region should be drawn with a dropshadow
+ *
+ * Creates a new attribute flagging a region to be drawn with a dropshadow
+ * or not.
+ *
+ * Return value: new #PangoAttribute
+ **/
+
+PangoAttribute *
+gdk_pango_attr_dropshadow_new (gboolean dropshadow)
+{
+  GdkPangoAttrDropshadow *result;
+  
+  static PangoAttrClass klass = {
+    0,
+    gdk_pango_attr_dropshadow_copy,
+    gdk_pango_attr_dropshadow_destroy,
+    gdk_pango_attr_dropshadow_compare
+  };
+
+  if (!klass.type)
+    klass.type = gdk_pango_attr_dropshadow_type =
+      pango_attr_type_register ("GdkPangoAttrDropshadow");
+
+  result = g_new (GdkPangoAttrDropshadow, 1);
+  result->attr.klass = &klass;
+  result->dropshadow = dropshadow;
   
   return (PangoAttribute *)result;
 }
Index: gdk/gdkpango.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkpango.h,v
retrieving revision 1.9
diff -u -p -r1.9 gdkpango.h
--- gdk/gdkpango.h	12 Jun 2005 05:32:24 -0000	1.9
+++ gdk/gdkpango.h	14 Sep 2006 01:28:42 -0000
@@ -133,6 +133,7 @@ GdkRegion    *gdk_pango_layout_get_clip_
 
 typedef struct _GdkPangoAttrStipple GdkPangoAttrStipple;
 typedef struct _GdkPangoAttrEmbossed GdkPangoAttrEmbossed;
+typedef struct _GdkPangoAttrDropshadow GdkPangoAttrDropshadow;
 
 struct _GdkPangoAttrStipple
 {
@@ -146,8 +147,15 @@ struct _GdkPangoAttrEmbossed
   gboolean embossed;
 };
 
+struct _GdkPangoAttrDropshadow
+{
+  PangoAttribute attr;
+  gboolean dropshadow;
+};
+
 PangoAttribute *gdk_pango_attr_stipple_new  (GdkBitmap *stipple);
 PangoAttribute *gdk_pango_attr_embossed_new (gboolean embossed);
+PangoAttribute *gdk_pango_attr_dropshadow_new (gboolean dropshadow);
 
 G_END_DECLS
 
