textview: add support for underline and strikethrough colors
authorChristian Hergert <christian@hergert.me>
Tue, 10 Feb 2015 00:41:48 +0000 (16:41 -0800)
committerMatthias Clasen <mclasen@redhat.com>
Wed, 18 Mar 2015 03:24:13 +0000 (23:24 -0400)
This commit adds the GtkTextTag:underline-rgba and :strikethrough-rgba
properties and the necessary plumbing to apply these colors in GtkTextLayout.
With this change, you can alter the color of underlines including those
of type PANGO_UNDERLINE_ERROR.

You might want to alter the underline color to differentiate between
spelling and grammer mistakes. In code editors, it is convenient to
differentiate between errors and warnings.

Note that the GtkTextAppearance struct is public ABI and has no spare
room for new fields, so we are resorting to some tricky packing to store
the colors in the unused pixel field of the fg_color and bg_color structs.
This packing is accomplished by the macros in gtktextattributesprivate.h.

Signed-off-by: Christian Hergert <christian@hergert.me>
https://bugzilla.gnome.org/show_bug.cgi?id=402168

gtk/Makefile.am
gtk/gtktextattributes.c
gtk/gtktextattributes.h
gtk/gtktextattributesprivate.h [new file with mode: 0644]
gtk/gtktextbuffer.c
gtk/gtktextdisplay.c
gtk/gtktextlayout.c
gtk/gtktexttag.c

index 83dfe31588b61c7dc20a086e18f34b04f3e87283..51153e6221964f842527aa745e0cec32935d0565 100644 (file)
@@ -500,6 +500,7 @@ gtk_private_h_sources =             \
        gtkstylecontextprivate.h \
        gtkstylepropertyprivate.h \
        gtkstyleproviderprivate.h \
+       gtktextattributesprivate.h \
        gtktextbtree.h          \
        gtktextbufferserialize.h \
        gtktextchildprivate.h   \
index b864f39bd36a5edb8c8d12fda4ef1d0abd913895..dc1360caf505316f5d48233edfd5087988abbe35 100644 (file)
@@ -50,6 +50,7 @@
 #include "config.h"
 
 #include "gtktextattributes.h"
+#include "gtktextattributesprivate.h"
 #include "gtktexttagprivate.h"
 
 /**
@@ -363,9 +364,27 @@ G_GNUC_END_IGNORE_DEPRECATIONS
       if (tag->priv->underline_set)
         dest->appearance.underline = vals->appearance.underline;
 
+      if (GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET (&vals->appearance))
+        {
+          GdkRGBA rgba;
+
+          GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA (&vals->appearance, &rgba);
+          GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA (&dest->appearance, &rgba);
+          GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA_SET (&dest->appearance, TRUE);
+        }
+
       if (tag->priv->strikethrough_set)
         dest->appearance.strikethrough = vals->appearance.strikethrough;
 
+      if (GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET (&vals->appearance))
+        {
+          GdkRGBA rgba;
+
+          GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA (&vals->appearance, &rgba);
+          GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA (&dest->appearance, &rgba);
+          GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA_SET (&dest->appearance, TRUE);
+        }
+
       if (tag->priv->invisible_set)
         dest->invisible = vals->invisible;
 
@@ -425,5 +444,7 @@ _gtk_text_tag_affects_nonsize_appearance (GtkTextTag *tag)
     priv->strikethrough_set ||
     priv->bg_full_height_set ||
     priv->pg_bg_color_set ||
-    priv->fallback_set;
+    priv->fallback_set ||
+    GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET (&priv->values->appearance) ||
+    GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance);
 }
index 4ee88c977fe2c7379a6da9150bf1454315b11d52..83a6312bd4158d414c8a52c342c489d306203e80 100644 (file)
@@ -89,8 +89,8 @@ typedef struct _GtkTextAppearance GtkTextAppearance;
 struct _GtkTextAppearance
 {
   /*< public >*/
-  GdkColor bg_color;
-  GdkColor fg_color;
+  GdkColor bg_color; /* pixel is taken for underline color */
+  GdkColor fg_color; /* pixel is taken for strikethrough color */
 
   /* super/subscript rise, can be negative */
   gint rise;
diff --git a/gtk/gtktextattributesprivate.h b/gtk/gtktextattributesprivate.h
new file mode 100644 (file)
index 0000000..45bc07b
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015 Christian Hergert <chergert@gnome.org>
+ *
+ * This program 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 program 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Christian Hergert <chergert@gnome.org>
+ *
+ */
+
+#ifndef __GTK_TEXT_ATTRIBUTE_PRIVATE_H__
+#define __GTK_TEXT_ATTRIBUTE_PRIVATE_H__
+
+/*
+ * The following macros are used to store and extract information about the
+ * Pango underline and strikethrough colors in the unused pixel member of
+ * the GdkColor members of GtkTextAppearance.
+ *
+ * In 4.0, we should revisit this.
+ */
+
+#define GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET(appr) \
+    (((guint8*)&(appr)->bg_color)[3] != 0)
+#define GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA_SET(appr,val) \
+  G_STMT_START { \
+    ((guint8*)&(appr)->bg_color)[3] = !!val; \
+  } G_STMT_END
+#define GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA(appr,rgba) \
+  G_STMT_START { \
+    (rgba)->red = ((guint8*)&(appr)->bg_color)[0] / 255.; \
+    (rgba)->green = ((guint8*)&(appr)->bg_color)[1] / 255.; \
+    (rgba)->blue = ((guint8*)&(appr)->bg_color)[2] / 255.; \
+    (rgba)->alpha = 1.0; \
+  } G_STMT_END
+#define GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA(appr,rgba) \
+  G_STMT_START { \
+    ((guint8*)&(appr)->bg_color)[0] = (rgba)->red * 255; \
+    ((guint8*)&(appr)->bg_color)[1] = (rgba)->green * 255; \
+    ((guint8*)&(appr)->bg_color)[2] = (rgba)->blue * 255; \
+  } G_STMT_END
+
+
+#define GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET(appr) \
+    (((guint8*)&(appr)->fg_color)[3] != 0)
+#define GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA_SET(appr,val) \
+  G_STMT_START { \
+    ((guint8*)&(appr)->fg_color)[3] = !!val; \
+  } G_STMT_END
+#define GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA(appr,rgba) \
+  G_STMT_START { \
+    (rgba)->red = ((guint8*)&(appr)->fg_color)[0] / 255.; \
+    (rgba)->green = ((guint8*)&(appr)->fg_color)[1] / 255.; \
+    (rgba)->blue = ((guint8*)&(appr)->fg_color)[2] / 255.; \
+    (rgba)->alpha = 1.0; \
+  } G_STMT_END
+#define GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA(appr,rgba) \
+  G_STMT_START { \
+    ((guint8*)&(appr)->fg_color)[0] = (rgba)->red * 255; \
+    ((guint8*)&(appr)->fg_color)[1] = (rgba)->green * 255; \
+    ((guint8*)&(appr)->fg_color)[2] = (rgba)->blue * 255; \
+  } G_STMT_END
+
+
+#endif /* __GTK_TEXT_ATTRIBUTE_PRIVATE_H__ */
index a4db3533a7f25cc5211da25249a460eba86d3d5c..1428fe20b97690ea68c0eb618d4b0459898f3974 100644 (file)
@@ -4793,10 +4793,38 @@ get_tag_for_attributes (PangoAttrIterator *iter)
   if (attr)
     g_object_set (tag, "underline", ((PangoAttrInt*)attr)->value, NULL);
 
+  attr = pango_attr_iterator_get (iter, PANGO_ATTR_UNDERLINE_COLOR);
+  if (attr)
+    {
+      PangoColor *color;
+      GdkRGBA rgba;
+
+      color = &((PangoAttrColor*)attr)->color;
+      rgba.red = color->red / 65535.;
+      rgba.green = color->green / 65535.;
+      rgba.blue = color->blue / 65535.;
+      rgba.alpha = 1.;
+      g_object_set (tag, "underline-rgba", &rgba, NULL);
+    }
+
   attr = pango_attr_iterator_get (iter, PANGO_ATTR_STRIKETHROUGH);
   if (attr)
     g_object_set (tag, "strikethrough", (gboolean) (((PangoAttrInt*)attr)->value != 0), NULL);
 
+  attr = pango_attr_iterator_get (iter, PANGO_ATTR_STRIKETHROUGH_COLOR);
+  if (attr)
+    {
+      PangoColor *color;
+      GdkRGBA rgba;
+
+      color = &((PangoAttrColor*)attr)->color;
+      rgba.red = color->red / 65535.;
+      rgba.green = color->green / 65535.;
+      rgba.blue = color->blue / 65535.;
+      rgba.alpha = 1.;
+      g_object_set (tag, "strikethrough-rgba", &rgba, NULL);
+    }
+
   attr = pango_attr_iterator_get (iter, PANGO_ATTR_RISE);
   if (attr)
     g_object_set (tag, "rise", ((PangoAttrInt*)attr)->value, NULL);
index 6be8fe2c8cf677879bc0ab649d93c9b7f2d0c5a6..f8178018800cc86e728ed914ef000ab2b67e4e18 100644 (file)
@@ -75,6 +75,7 @@
 
 #define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
 #include "config.h"
+#include "gtktextattributesprivate.h"
 #include "gtktextdisplay.h"
 #include "gtkwidgetprivate.h"
 #include "gtkstylecontextprivate.h"
@@ -204,9 +205,25 @@ gtk_text_renderer_prepare_run (PangoRenderer  *renderer,
     fg_rgba = appearance->rgba[1];
 
   text_renderer_set_rgba (text_renderer, PANGO_RENDER_PART_FOREGROUND, fg_rgba);
-  text_renderer_set_rgba (text_renderer, PANGO_RENDER_PART_STRIKETHROUGH, fg_rgba);
 
-  if (appearance->underline == PANGO_UNDERLINE_ERROR)
+  if (GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET (appearance))
+    {
+      GdkRGBA rgba;
+
+      GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA (appearance, &rgba);
+      text_renderer_set_rgba (text_renderer, PANGO_RENDER_PART_STRIKETHROUGH, &rgba);
+    }
+  else
+    text_renderer_set_rgba (text_renderer, PANGO_RENDER_PART_STRIKETHROUGH, fg_rgba);
+
+  if (GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET (appearance))
+    {
+      GdkRGBA rgba;
+
+      GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA (appearance, &rgba);
+      text_renderer_set_rgba (text_renderer, PANGO_RENDER_PART_UNDERLINE, &rgba);
+    }
+  else if (appearance->underline == PANGO_UNDERLINE_ERROR)
     {
       if (!text_renderer->error_color)
         {
index da3a0e8de2dbbb64ccc362779c1a13db38761604..00dbefae04143aa2ec16ce16d6afb6405603e8a2 100644 (file)
@@ -81,6 +81,7 @@
 #include "gtktextlayout.h"
 #include "gtktextbtree.h"
 #include "gtktextiterprivate.h"
+#include "gtktextattributesprivate.h"
 #include "gtktextutil.h"
 #include "gtkintl.h"
 
@@ -1447,6 +1448,38 @@ rgba_equal (const GdkRGBA *rgba1, const GdkRGBA *rgba2)
   return TRUE;
 }
 
+static gboolean
+underline_equal (const GtkTextAppearance *appearance1,
+                 const GtkTextAppearance *appearance2)
+{
+  GdkRGBA c1;
+  GdkRGBA c2;
+
+  GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA (appearance1, &c1);
+  GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA (appearance2, &c2);
+
+  return ((appearance1->underline == appearance2->underline) &&
+          (GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET (appearance1) ==
+           GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET (appearance2)) &&
+          gdk_rgba_equal (&c1, &c2));
+}
+
+static gboolean
+strikethrough_equal (const GtkTextAppearance *appearance1,
+                     const GtkTextAppearance *appearance2)
+{
+  GdkRGBA c1;
+  GdkRGBA c2;
+
+  GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA (appearance1, &c1);
+  GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA (appearance2, &c2);
+
+  return ((appearance1->strikethrough == appearance2->strikethrough) &&
+          (GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET (appearance1) ==
+           GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET (appearance2)) &&
+          gdk_rgba_equal (&c1, &c2));
+}
+
 static gboolean
 gtk_text_attr_appearance_compare (const PangoAttribute *attr1,
                                   const PangoAttribute *attr2)
@@ -1456,9 +1489,9 @@ gtk_text_attr_appearance_compare (const PangoAttribute *attr1,
 
   return (rgba_equal (appearance1->rgba[0], appearance2->rgba[0]) &&
           rgba_equal (appearance1->rgba[1], appearance2->rgba[1]) &&
-          appearance1->underline == appearance2->underline &&
-          appearance1->strikethrough == appearance2->strikethrough &&
-          appearance1->draw_bg == appearance2->draw_bg);
+          appearance1->draw_bg == appearance2->draw_bg &&
+          strikethrough_equal (appearance1, appearance2) &&
+          underline_equal (appearance1, appearance2));
 }
 
 /*
@@ -1522,6 +1555,22 @@ add_generic_attrs (GtkTextLayout      *layout,
       pango_attr_list_insert (attrs, attr);
     }
 
+  if (GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET (appearance))
+    {
+      GdkRGBA rgba;
+
+      GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA (appearance, &rgba);
+
+      attr = pango_attr_underline_color_new (rgba.red * 65535,
+                                             rgba.green * 65535,
+                                             rgba.blue * 65535);
+
+      attr->start_index = start;
+      attr->end_index = start + byte_count;
+
+      pango_attr_list_insert (attrs, attr);
+    }
+
   if (appearance->strikethrough)
     {
       attr = pango_attr_strikethrough_new (appearance->strikethrough);
@@ -1532,6 +1581,22 @@ add_generic_attrs (GtkTextLayout      *layout,
       pango_attr_list_insert (attrs, attr);
     }
 
+  if (GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET (appearance))
+    {
+      GdkRGBA rgba;
+
+      GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA (appearance, &rgba);
+
+      attr = pango_attr_strikethrough_color_new (rgba.red * 65535,
+                                                 rgba.green * 65535,
+                                                 rgba.blue * 65535);
+
+      attr->start_index = start;
+      attr->end_index = start + byte_count;
+
+      pango_attr_list_insert (attrs, attr);
+    }
+
   if (appearance->rise != 0)
     {
       attr = pango_attr_rise_new (appearance->rise);
@@ -1935,9 +2000,18 @@ add_preedit_attrs (GtkTextLayout     *layout,
            case PANGO_ATTR_UNDERLINE:
              appearance.underline = ((PangoAttrInt *)attr)->value;
              break;
+            case PANGO_ATTR_UNDERLINE_COLOR:
+              convert_color (&rgba, (PangoAttrColor*)attr);
+              GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA_SET (&appearance, TRUE);
+              GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA (&appearance, &rgba);
+             break;
            case PANGO_ATTR_STRIKETHROUGH:
              appearance.strikethrough = ((PangoAttrInt *)attr)->value;
              break;
+            case PANGO_ATTR_STRIKETHROUGH_COLOR:
+              convert_color (&rgba, (PangoAttrColor*)attr);
+              GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA_SET (&appearance, TRUE);
+              GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA (&appearance, &rgba);
             case PANGO_ATTR_RISE:
               appearance.rise = ((PangoAttrInt *)attr)->value;
               break;
index e469d46792eddd0fe0359be6460c647e09fd095d..f5f34f0c3244f2f935e8eeecc2f8750b1b90a6ea 100644 (file)
@@ -74,6 +74,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "gtktextattributesprivate.h"
 #include "gtktexttag.h"
 #include "gtktexttypes.h"
 #include "gtktexttagtable.h"
@@ -119,8 +120,10 @@ enum {
   PROP_LEFT_MARGIN,
   PROP_INDENT,
   PROP_STRIKETHROUGH,
+  PROP_STRIKETHROUGH_RGBA,
   PROP_RIGHT_MARGIN,
   PROP_UNDERLINE,
+  PROP_UNDERLINE_RGBA,
   PROP_RISE,
   PROP_BACKGROUND_FULL_HEIGHT,
   PROP_LANGUAGE,
@@ -154,8 +157,10 @@ enum {
   PROP_LEFT_MARGIN_SET,
   PROP_INDENT_SET,
   PROP_STRIKETHROUGH_SET,
+  PROP_STRIKETHROUGH_RGBA_SET,
   PROP_RIGHT_MARGIN_SET,
   PROP_UNDERLINE_SET,
+  PROP_UNDERLINE_RGBA_SET,
   PROP_RISE_SET,
   PROP_BACKGROUND_FULL_HEIGHT_SET,
   PROP_LANGUAGE_SET,
@@ -518,7 +523,43 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
                                                       PANGO_TYPE_UNDERLINE,
                                                       PANGO_UNDERLINE_NONE,
                                                       GTK_PARAM_READWRITE));
-  
+
+  /**
+   * GtkTextTag:underline-rgba:
+   *
+   * This property modifies the color of underlines. If not set, underlines
+   * will use the forground color.
+   *
+   * If #GtkTextTag:underline is set to %PANGO_UNDERLINE_ERROR, an alternate
+   * color may be applied instead of the foreground. Setting this property
+   * will always override those defaults.
+   *
+   * Since: 3.18
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_UNDERLINE_RGBA,
+                                   g_param_spec_boxed ("underline-rgba",
+                                                       P_("Underline RGBA"),
+                                                       P_("Color of underline for this text"),
+                                                       GDK_TYPE_RGBA,
+                                                       GTK_PARAM_READWRITE));
+
+  /**
+   * GtkTextTag:strikethrough-rgba:
+   *
+   * This property modifies the color of strikeouts. If not set, strikeouts
+   * will use the forground color.
+   *
+   * Since: 3.18
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_STRIKETHROUGH_RGBA,
+                                   g_param_spec_boxed ("strikethrough-rgba",
+                                                       P_("Strike-through RGBA"),
+                                                       P_("Color of strike-through for this text"),
+                                                       GDK_TYPE_RGBA,
+                                                       GTK_PARAM_READWRITE));
+
   g_object_class_install_property (object_class,
                                    PROP_WRAP_MODE,
                                    g_param_spec_enum ("wrap-mode",
@@ -746,6 +787,28 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
                 P_("Underline set"),
                 P_("Whether this tag affects underlining"));
 
+  /**
+   * GtkTextTag:underline-rgba-set:
+   *
+   * If the #GtkTextTag:underline-rgba property has been set.
+   *
+   * Since: 3.18
+   */
+  ADD_SET_PROP ("underline-rgba-set", PROP_UNDERLINE_RGBA_SET,
+                P_("Underline RGBA set"),
+                P_("Whether this tag affects underlining color"));
+
+  /**
+   * GtkTextTag:strikethrough-rgba-set:
+   *
+   * If the #GtkTextTag:strikethrough-rgba property has been set.
+   *
+   * Since: 3.18
+   */
+  ADD_SET_PROP ("strikethrough-rgba-set", PROP_STRIKETHROUGH_RGBA_SET,
+                P_("Strikethrough RGBA set"),
+                P_("Whether this tag affects strikethrough color"));
+
   ADD_SET_PROP ("wrap-mode-set", PROP_WRAP_MODE_SET,
                 P_("Wrap mode set"),
                 P_("Whether this tag affects line wrap mode"));
@@ -862,6 +925,66 @@ copy_gdk_color_to_rgba (GdkColor *src,
   dest->alpha = 1;
 }
 
+static void
+set_underline_rgba (GtkTextTag    *tag,
+                    const GdkRGBA *rgba)
+{
+  GtkTextTagPrivate *priv = tag->priv;
+
+  if (rgba)
+    {
+      GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA (&priv->values->appearance, rgba);
+
+      if (!GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET (&priv->values->appearance))
+        {
+          GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA_SET (&priv->values->appearance, TRUE);
+          g_object_notify (G_OBJECT (tag), "underline-rgba-set");
+        }
+    }
+  else
+    {
+      GdkRGBA black = { 0 };
+
+      GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA (&priv->values->appearance, &black);
+
+      if (GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET (&priv->values->appearance))
+        {
+          GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA_SET (&priv->values->appearance, FALSE);
+          g_object_notify (G_OBJECT (tag), "underline-rgba-set");
+        }
+    }
+}
+
+static void
+set_strikethrough_rgba (GtkTextTag    *tag,
+                        const GdkRGBA *rgba)
+{
+  GtkTextTagPrivate *priv = tag->priv;
+
+  if (rgba)
+    {
+      GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA (&priv->values->appearance, rgba);
+
+      if (!GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance))
+        {
+          GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance, TRUE);
+          g_object_notify (G_OBJECT (tag), "strikethrough-rgba-set");
+        }
+    }
+  else
+    {
+      GdkRGBA black = { 0 };
+
+      GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA (&priv->values->appearance, &black);
+
+      if (GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance))
+        {
+          GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance, FALSE);
+          g_object_notify (G_OBJECT (tag), "strikethrough-rgba-set");
+        }
+    }
+}
+
 static void
 set_bg_rgba (GtkTextTag *tag, GdkRGBA *rgba)
 {
@@ -1409,6 +1532,13 @@ gtk_text_tag_set_property (GObject      *object,
       g_object_notify (object, "strikethrough-set");
       break;
 
+    case PROP_STRIKETHROUGH_RGBA:
+      {
+        GdkRGBA *color = g_value_get_boxed (value);
+        set_strikethrough_rgba (text_tag, color);
+      }
+      break;
+
     case PROP_RIGHT_MARGIN:
       priv->right_margin_set = TRUE;
       priv->values->right_margin = g_value_get_int (value);
@@ -1422,6 +1552,13 @@ gtk_text_tag_set_property (GObject      *object,
       g_object_notify (object, "underline-set");
       break;
 
+    case PROP_UNDERLINE_RGBA:
+      {
+        GdkRGBA *color = g_value_get_boxed (value);
+        set_underline_rgba (text_tag, color);
+      }
+      break;
+
     case PROP_RISE:
       priv->rise_set = TRUE;
       priv->values->appearance.rise = g_value_get_int (value);
@@ -1593,6 +1730,11 @@ gtk_text_tag_set_property (GObject      *object,
       priv->strikethrough_set = g_value_get_boolean (value);
       break;
 
+    case PROP_STRIKETHROUGH_RGBA_SET:
+      GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance,
+                                                      g_value_get_boolean (value));
+      break;
+
     case PROP_RIGHT_MARGIN_SET:
       priv->right_margin_set = g_value_get_boolean (value);
       size_changed = TRUE;
@@ -1602,6 +1744,11 @@ gtk_text_tag_set_property (GObject      *object,
       priv->underline_set = g_value_get_boolean (value);
       break;
 
+    case PROP_UNDERLINE_RGBA_SET:
+      GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA_SET (&priv->values->appearance,
+                                                  g_value_get_boolean (value));
+      break;
+
     case PROP_RISE_SET:
       priv->rise_set = g_value_get_boolean (value);
       size_changed = TRUE;
@@ -1790,6 +1937,16 @@ gtk_text_tag_get_property (GObject      *object,
       g_value_set_boolean (value, priv->values->appearance.strikethrough);
       break;
 
+    case PROP_STRIKETHROUGH_RGBA:
+      if (GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance))
+        {
+          GdkRGBA rgba;
+
+          GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA (&priv->values->appearance, &rgba);
+          g_value_set_boxed (value, &rgba);
+        }
+      break;
+
     case PROP_RIGHT_MARGIN:
       g_value_set_int (value, priv->values->right_margin);
       break;
@@ -1798,6 +1955,16 @@ gtk_text_tag_get_property (GObject      *object,
       g_value_set_enum (value, priv->values->appearance.underline);
       break;
 
+    case PROP_UNDERLINE_RGBA:
+      if (GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET (&priv->values->appearance))
+        {
+          GdkRGBA rgba;
+
+          GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA (&priv->values->appearance, &rgba);
+          g_value_set_boxed (value, &rgba);
+        }
+      break;
+
     case PROP_RISE:
       g_value_set_int (value, priv->values->appearance.rise);
       break;
@@ -1901,6 +2068,11 @@ gtk_text_tag_get_property (GObject      *object,
       g_value_set_boolean (value, priv->strikethrough_set);
       break;
 
+    case PROP_STRIKETHROUGH_RGBA_SET:
+      g_value_set_boolean (value,
+                           GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance));
+      break;
+
     case PROP_RIGHT_MARGIN_SET:
       g_value_set_boolean (value, priv->right_margin_set);
       break;
@@ -1909,6 +2081,11 @@ gtk_text_tag_get_property (GObject      *object,
       g_value_set_boolean (value, priv->underline_set);
       break;
 
+    case PROP_UNDERLINE_RGBA_SET:
+      g_value_set_boolean (value,
+                           GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET (&priv->values->appearance));
+      break;
+
     case PROP_RISE_SET:
       g_value_set_boolean (value, priv->rise_set);
       break;