diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 5e5e585..bdede7b 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -68,8 +68,15 @@ static GHashTable *name_map = NULL;
 PangoAttrType
 pango_attr_type_register (const gchar *name)
 {
-  static guint current_type = 0x1000000;
-  guint type = current_type++;
+  pango_attr_type_register_similar (name, PANGO_ATTR_INVALID);
+}
+
+PangoAttrType
+pango_attr_type_register_similar (const gchar   *name,
+				  PangoAttrType  similar_type)
+{
+  static guint current_type = 1;
+  guint type = current_type++ | (int)similar_type << 24;
 
   if (name)
     {
@@ -82,6 +89,27 @@ pango_attr_type_register (const gchar *name)
   return type;
 }
 
+PangoAttrType
+pango_attr_type_get_base_type (PangoAttrType attr_type)
+{
+  return attr_type >> 24;
+}
+
+gboolean
+pango_attr_type_is_similar (PangoAttrType first_type,
+			    PangoAttrType second_type)
+{
+  return (pango_attr_type_get_base_type (first_type) == second_type ||
+	  pango_attr_type_get_base_type (second_type) == first_type);
+}
+
+gboolean
+pango_attr_similar_to (PangoAttribute *attr,
+		       PangoAttrType   other_type)
+{
+  return pango_attr_type_is_similar (attr->klass->type, other_type);
+}
+
 /**
  * pango_attr_type_get_name:
  * @type: an attribute type ID to fetch the name for
@@ -475,7 +503,7 @@ pango_attr_size_copy (const PangoAttribute *attr)
 {
   const PangoAttrSize *size_attr = (PangoAttrSize *)attr;
 
-  if (attr->klass->type == PANGO_ATTR_ABSOLUTE_SIZE)
+  if (pango_attr_type_get_base_type (attr->klass->type) == PANGO_ATTR_ABSOLUTE_SIZE)
     return pango_attr_size_new_absolute (size_attr->size);
   else
     return pango_attr_size_new (size_attr->size);
@@ -1828,7 +1856,7 @@ pango_attr_iterator_get_font (PangoAttrIterator     *iterator,
       PangoAttribute *attr = tmp_list1->data;
       tmp_list1 = tmp_list1->next;
 
-      switch (attr->klass->type)
+      switch (pango_attr_type_get_base_type (attr->klass->type))
 	{
 	case PANGO_ATTR_FONT_DESC:
 	  {
diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h
index d4ce840..b293a99 100644
--- a/pango/pango-attributes.h
+++ b/pango/pango-attributes.h
@@ -176,8 +176,15 @@ struct _PangoAttrFontDesc
   PangoFontDescription *desc;
 };
 
-PangoAttrType         pango_attr_type_register (const gchar        *name);
-G_CONST_RETURN char * pango_attr_type_get_name (PangoAttrType       type) G_GNUC_CONST;
+PangoAttrType         pango_attr_type_register         (const gchar   *name);
+PangoAttrType         pango_attr_type_register_similar (const char    *name,
+							PangoAttrType  similar_type);
+G_CONST_RETURN char * pango_attr_type_get_name         (PangoAttrType  type) G_GNUC_CONST;
+PangoAttrType         pango_attr_type_get_base_type    (PangoAttrType  attr_type);
+gboolean              pango_attr_type_is_similar       (PangoAttrType first_type,
+							PangoAttrType second_type);
+gboolean              pango_attr_similar_to            (PangoAttribute *attr,
+							PangoAttrType   other_type);
 
 void             pango_attribute_init        (PangoAttribute       *attr,
 					      const PangoAttrClass *klass);
diff --git a/pango/pangocairo-context.c b/pango/pangocairo-context.c
index 455f5e4..083d844 100644
--- a/pango/pangocairo-context.c
+++ b/pango/pangocairo-context.c
@@ -27,7 +27,15 @@
 
 #include <string.h>
 
-typedef struct _PangoCairoContextInfo PangoCairoContextInfo;
+typedef struct _PangoCairoContextInfo       PangoCairoContextInfo;
+typedef struct _PangoCairoShapeRendererInfo PangoCairoShapeRendererInfo;
+
+struct _PangoCairoShapeRendererInfo
+{
+  PangoCairoShapeRendererFunc shape_renderer_func;
+  gpointer                    shape_renderer_data;
+  GDestroyNotify              shape_renderer_notify;
+};
 
 struct _PangoCairoContextInfo
 {
@@ -37,25 +45,41 @@ struct _PangoCairoContextInfo
   cairo_font_options_t *surface_options;
   cairo_font_options_t *merged_options;
 
+  GHashTable *shape_renderers;
+
+#if 0
   PangoCairoShapeRendererFunc shape_renderer_func;
   gpointer                    shape_renderer_data;
   GDestroyNotify              shape_renderer_notify;
+#endif
 };
 
 static void
+free_shape_renderer_info (gpointer key,
+			  gpointer value,
+			  gpointer data)
+{
+  PangoCairoShapeRendererInfo *info = value;
+
+  if (info->shape_renderer_notify)
+    info->shape_renderer_notify (info->shape_renderer_data);
+
+  g_slice_free (PangoCairoShapeRendererInfo, info);
+}
+
+static void
 free_context_info (PangoCairoContextInfo *info)
 {
+  if (info->shape_renderers)
+    g_hash_table_foreach (info->shape_renderers,
+			  free_shape_renderer_info, NULL);
+
   if (info->set_options)
     cairo_font_options_destroy (info->set_options);
   if (info->surface_options)
     cairo_font_options_destroy (info->surface_options);
   if (info->merged_options)
     cairo_font_options_destroy (info->merged_options);
-
-  if (info->shape_renderer_notify)
-    info->shape_renderer_notify (info->shape_renderer_data);
-
-  g_slice_free (PangoCairoContextInfo, info);
 }
 
 static PangoCairoContextInfo *
@@ -325,18 +349,46 @@ pango_cairo_context_set_shape_renderer (PangoContext                *context,
 					gpointer                     data,
 					GDestroyNotify               dnotify)
 {
+  pango_cairo_context_set_shape_renderer_for_attr_type (context,
+							PANGO_ATTR_SHAPE,
+							func,
+							data,
+							dnotify);
+}
+
+void
+pango_cairo_context_set_shape_renderer_for_attr_type (PangoContext                *context,
+						      PangoAttrType                attr_type,
+						      PangoCairoShapeRendererFunc  func,
+						      gpointer                     data,
+						      GDestroyNotify               dnotify)
+{
   PangoCairoContextInfo *info;
+  PangoCairoShapeRendererInfo *renderer_info;
 
   g_return_if_fail (PANGO_IS_CONTEXT (context));
+  g_return_if_fail (pango_attr_type_get_base_type (attr_type) != PANGO_ATTR_SHAPE);
 
-  info  = get_context_info (context, TRUE);
+  info = get_context_info (context, TRUE);
 
-  if (info->shape_renderer_notify)
-    info->shape_renderer_notify (info->shape_renderer_data);
+  if (!info->shape_renderers)
+    info->shape_renderers = g_hash_table_new (g_int_hash, g_int_equal);
+
+  renderer_info = g_hash_table_lookup (info->shape_renderers, GUINT_TO_POINTER (attr_type));
+  if (!renderer_info)
+    {
+      renderer_info = g_slice_new0 (PangoCairoShapeRendererInfo);
+      g_hash_table_insert (info->shape_renderers,
+			   GUINT_TO_POINTER (attr_type),
+			   renderer_info);
+    }
+
+  if (renderer_info->shape_renderer_notify)
+    renderer_info->shape_renderer_notify (renderer_info->shape_renderer_data);
 
-  info->shape_renderer_func   = func;
-  info->shape_renderer_data   = data;
-  info->shape_renderer_notify = dnotify;
+  renderer_info->shape_renderer_func   = func;
+  renderer_info->shape_renderer_data   = data;
+  renderer_info->shape_renderer_notify = dnotify;
 }
 
 /**
@@ -358,27 +410,42 @@ pango_cairo_context_set_shape_renderer (PangoContext                *context,
  * Since: 1.18
  */
 PangoCairoShapeRendererFunc
-pango_cairo_context_get_shape_renderer (PangoContext                *context,
-					gpointer                    *data)
+pango_cairo_context_get_shape_renderer (PangoContext *context,
+					gpointer     *data)
+{
+  return pango_cairo_context_get_shape_renderer_for_attr_type (context,
+							       PANGO_ATTR_SHAPE,
+							       data);
+}
+
+PangoCairoShapeRendererFunc
+pango_cairo_context_get_shape_renderer_for_attr_type (PangoContext   *context,
+						      PangoAttrType   attr_type,
+						      gpointer       *data)
 {
   PangoCairoContextInfo *info;
+  PangoCairoShapeRendererInfo *renderer_info;
 
   g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL);
+  g_return_val_if_fail (pango_attr_type_get_base_type (attr_type) != PANGO_ATTR_SHAPE, NULL);
 
   info = get_context_info (context, FALSE);
 
   if (info)
     {
-      if (data)
-        *data = info->shape_renderer_data;
-      return info->shape_renderer_func;
-    }
-  else
-    {
-      if (data)
-        *data = NULL;
-      return NULL;
+      renderer_info = g_hash_table_lookup (info->shape_renderers,
+					   GUINT_TO_POINTER (attr_type));
+      if (renderer_info)
+	{
+	  if (data)
+	    *data = renderer_info->shape_renderer_data;
+	  return renderer_info->shape_renderer_func;
+	}
     }
+
+  if (data)
+    *data = NULL;
+  return NULL;
 }
 
 /**
diff --git a/pango/pangocairo.h b/pango/pangocairo.h
index f6fc261..c5c724f 100644
--- a/pango/pangocairo.h
+++ b/pango/pangocairo.h
@@ -102,8 +102,16 @@ void                        pango_cairo_context_set_shape_renderer (PangoContext
 								    PangoCairoShapeRendererFunc  func,
 								    gpointer                     data,
 								    GDestroyNotify               dnotify);
-PangoCairoShapeRendererFunc pango_cairo_context_get_shape_renderer (PangoContext                *context,
-								    gpointer                    *data);
+void          pango_cairo_context_set_shape_renderer_for_attr_type (PangoContext                *context,
+								    PangoAttrType                attr_type,
+								    PangoCairoShapeRendererFunc  func,
+								    gpointer                     data,
+								    GDestroyNotify               dnotify);
+PangoCairoShapeRendererFunc pango_cairo_context_get_shape_renderer               (PangoContext   *context,
+										  gpointer       *data);
+PangoCairoShapeRendererFunc pango_cairo_context_get_shape_renderer_for_attr_type (PangoContext   *context,
+										  PangoAttrType   attr_type,
+										  gpointer       *data);
 
 /* Convenience
  */
