[gimp] Bug 620674 - Adding support for multi-colored text layer



commit ad819263af66224d6c60e37a0adbbb695a06575b
Author: Michael Natterer <mitch gimp org>
Date:   Thu Sep 2 00:20:04 2010 +0200

    Bug 620674 - Adding support for multi-colored text layer
    
    Apply slightly modified patch from Barak Itkin that adds colors for
    text spans plus GUI to edit these colors.

 app/widgets/gimptextbuffer.c      |  137 +++++++++++++++++++++++++++++++++++++
 app/widgets/gimptextbuffer.h      |    9 +++
 app/widgets/gimptextstyleeditor.c |   93 +++++++++++++++++++++++++
 app/widgets/gimptextstyleeditor.h |    2 +
 app/widgets/gimptexttag.c         |   20 ++++++
 app/widgets/gimptexttag.h         |    3 +
 6 files changed, 264 insertions(+), 0 deletions(-)
---
diff --git a/app/widgets/gimptextbuffer.c b/app/widgets/gimptextbuffer.c
index 99b7fe8..76e17cc 100644
--- a/app/widgets/gimptextbuffer.c
+++ b/app/widgets/gimptextbuffer.c
@@ -42,12 +42,14 @@
 #include <gtk/gtk.h>
 
 #include "libgimpbase/gimpbase.h"
+#include "libgimpcolor/gimpcolor.h"
 
 #include "widgets-types.h"
 
 #include "gimptextbuffer.h"
 #include "gimptextbuffer-serialize.h"
 #include "gimptexttag.h"
+#include "gimpwidgets-utils.h"
 
 #include "gimp-intl.h"
 
@@ -172,6 +174,12 @@ gimp_text_buffer_finalize (GObject *object)
       buffer->font_tags = NULL;
     }
 
+  if (buffer->color_tags)
+    {
+      g_list_free (buffer->color_tags);
+      buffer->color_tags = NULL;
+    }
+
   gimp_text_buffer_clear_insert_tags (buffer);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -908,12 +916,112 @@ gimp_text_buffer_set_font (GimpTextBuffer    *buffer,
   gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer));
 }
 
+GtkTextTag *
+gimp_text_buffer_get_iter_color (GimpTextBuffer    *buffer,
+                                 const GtkTextIter *iter,
+                                 GimpRGB           *color)
+{
+  GList *list;
+
+  for (list = buffer->color_tags; list; list = g_list_next (list))
+    {
+      GtkTextTag *tag = list->data;
+
+      if (gtk_text_iter_has_tag (iter, tag))
+        {
+          if (color)
+            gimp_text_tag_get_color (tag, color);
+
+          return tag;
+        }
+    }
+
+  return NULL;
+}
+
+static GtkTextTag *
+gimp_text_buffer_get_color_tag (GimpTextBuffer *buffer,
+                                const GimpRGB  *color)
+{
+  GList      *list;
+  GtkTextTag *tag;
+  gchar       name[256];
+  GdkColor    gdk_color;
+
+  for (list = buffer->color_tags; list; list = g_list_next (list))
+    {
+      GimpRGB tag_color;
+
+      tag = list->data;
+
+      gimp_text_tag_get_color (tag, &tag_color);
+
+      /* Do not compare the alpha channel, since it's unused */
+      if (tag_color.r == color->r &&
+          tag_color.g == color->g &&
+          tag_color.b == color->b)
+        {
+          return tag;
+        }
+    }
+
+  g_snprintf (name, sizeof (name), "color-(%0.f,%0.f,%0.f)",
+              color->r, color->g, color->b);
+
+  gimp_rgb_get_gdk_color (color, &gdk_color);
+
+  tag = gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (buffer),
+                                    name,
+                                    "foreground-gdk", &gdk_color,
+                                    "foreground-set", TRUE,
+                                    NULL);
+
+  buffer->color_tags = g_list_prepend (buffer->color_tags, tag);
+
+  return tag;
+}
+
+void
+gimp_text_buffer_set_color (GimpTextBuffer    *buffer,
+                            const GtkTextIter *start,
+                            const GtkTextIter *end,
+                            const GimpRGB     *color)
+{
+  GList *list;
+
+  g_return_if_fail (GIMP_IS_TEXT_BUFFER (buffer));
+  g_return_if_fail (start != NULL);
+  g_return_if_fail (end != NULL);
+
+  if (gtk_text_iter_equal (start, end))
+    return;
+
+  gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer));
+
+  for (list = buffer->color_tags; list; list = g_list_next (list))
+    {
+      gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (buffer), list->data,
+                                  start, end);
+    }
+
+  if (color)
+    {
+      GtkTextTag *tag = gimp_text_buffer_get_color_tag (buffer, color);
+
+      gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (buffer), tag,
+                                 start, end);
+    }
+
+  gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer));
+}
+
 /*  Pango markup attribute names  */
 
 #define GIMP_TEXT_ATTR_NAME_SIZE     "size"
 #define GIMP_TEXT_ATTR_NAME_BASELINE "rise"
 #define GIMP_TEXT_ATTR_NAME_KERNING  "letter_spacing"
 #define GIMP_TEXT_ATTR_NAME_FONT     "font"
+#define GIMP_TEXT_ATTR_NAME_COLOR    "foreground"
 
 const gchar *
 gimp_text_buffer_tag_to_name (GimpTextBuffer  *buffer,
@@ -986,6 +1094,24 @@ gimp_text_buffer_tag_to_name (GimpTextBuffer  *buffer,
 
       return "span";
     }
+  else if (g_list_find (buffer->color_tags, tag))
+    {
+      if (attribute)
+        *attribute = GIMP_TEXT_ATTR_NAME_COLOR;
+
+      if (value)
+        {
+          GimpRGB color;
+          guchar  r, g, b;
+
+          gimp_text_tag_get_color (tag, &color);
+          gimp_rgb_get_uchar (&color, &r, &g, &b);
+
+          *value = g_strdup_printf ("#%02x%02x%02x", r, g, b);
+        }
+
+      return "span";
+    }
 
   return NULL;
 }
@@ -1035,6 +1161,17 @@ gimp_text_buffer_name_to_tag (GimpTextBuffer *buffer,
         {
           return gimp_text_buffer_get_font_tag (buffer, value);
         }
+      else if (! strcmp (attribute, GIMP_TEXT_ATTR_NAME_COLOR))
+        {
+          GimpRGB color;
+          guint   r, g, b;
+
+          sscanf (value, "#%02x%02x%02x", &r, &g, &b);
+
+          gimp_rgb_set_uchar (&color, r, g, b);
+
+          return gimp_text_buffer_get_color_tag (buffer, &color);
+        }
     }
 
   return NULL;
diff --git a/app/widgets/gimptextbuffer.h b/app/widgets/gimptextbuffer.h
index 1e46598..11ae4f5 100644
--- a/app/widgets/gimptextbuffer.h
+++ b/app/widgets/gimptextbuffer.h
@@ -44,6 +44,7 @@ struct _GimpTextBuffer
   GList         *baseline_tags;
   GList         *kerning_tags;
   GList         *font_tags;
+  GList         *color_tags;
 
   gboolean       insert_tags_set;
   GList         *insert_tags;
@@ -116,6 +117,14 @@ void             gimp_text_buffer_set_font          (GimpTextBuffer    *buffer,
                                                      const GtkTextIter *end,
                                                      const gchar       *font);
 
+GtkTextTag     * gimp_text_buffer_get_iter_color    (GimpTextBuffer    *buffer,
+                                                     const GtkTextIter *iter,
+                                                     GimpRGB           *color);
+void             gimp_text_buffer_set_color         (GimpTextBuffer    *buffer,
+                                                     const GtkTextIter *start,
+                                                     const GtkTextIter *end,
+                                                     const GimpRGB     *color);
+
 const gchar    * gimp_text_buffer_tag_to_name       (GimpTextBuffer    *buffer,
                                                      GtkTextTag        *tag,
                                                      const gchar      **attribute,
diff --git a/app/widgets/gimptextstyleeditor.c b/app/widgets/gimptextstyleeditor.c
index f0f6da4..4f23406 100644
--- a/app/widgets/gimptextstyleeditor.c
+++ b/app/widgets/gimptextstyleeditor.c
@@ -24,6 +24,7 @@
 #include <gtk/gtk.h>
 
 #include "libgimpbase/gimpbase.h"
+#include "libgimpcolor/gimpcolor.h"
 #include "libgimpwidgets/gimpwidgets.h"
 
 #include "widgets-types.h"
@@ -80,6 +81,11 @@ static void      gimp_text_style_editor_font_changed     (GimpContext         *c
 static void      gimp_text_style_editor_set_font         (GimpTextStyleEditor *editor,
                                                           GtkTextTag          *font_tag);
 
+static void      gimp_text_style_editor_color_changed    (GimpColorButton     *button,
+                                                          GimpTextStyleEditor *editor);
+static void      gimp_text_style_editor_set_color        (GimpTextStyleEditor *editor,
+                                                          GtkTextTag          *color_tag);
+
 static void      gimp_text_style_editor_tag_toggled      (GtkToggleButton     *toggle,
                                                           GimpTextStyleEditor *editor);
 static void      gimp_text_style_editor_set_toggle       (GimpTextStyleEditor *editor,
@@ -166,6 +172,7 @@ static void
 gimp_text_style_editor_init (GimpTextStyleEditor *editor)
 {
   GtkWidget *image;
+  GimpRGB    color;
 
   /*  upper row  */
 
@@ -195,6 +202,19 @@ gimp_text_style_editor_init (GimpTextStyleEditor *editor)
                     G_CALLBACK (gimp_text_style_editor_size_changed),
                     editor);
 
+  gimp_rgb_set (&color, 0.0, 0.0, 0.0);
+  editor->color_button = gimp_color_button_new (_("Change color of selected text"),
+                                                20, 20, &color,
+                                                GIMP_COLOR_AREA_FLAT);
+
+  gtk_box_pack_start (GTK_BOX (editor->upper_hbox), editor->color_button,
+                      FALSE, FALSE, 0);
+  gtk_widget_show (editor->color_button);
+
+  g_signal_connect (editor->color_button, "color-changed",
+                    G_CALLBACK (gimp_text_style_editor_color_changed),
+                    editor);
+
   /*  lower row  */
 
   editor->lower_hbox = gtk_hbox_new (FALSE, 0);
@@ -568,6 +588,46 @@ gimp_text_style_editor_set_font (GimpTextStyleEditor *editor,
 }
 
 static void
+gimp_text_style_editor_color_changed (GimpColorButton     *button,
+                                      GimpTextStyleEditor *editor)
+{
+  GtkTextBuffer *buffer = GTK_TEXT_BUFFER (editor->buffer);
+  GtkTextIter    start, end;
+  GimpRGB        color;
+
+  if (! gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
+    {
+      return;
+    }
+
+  gimp_color_button_get_color (button, &color);
+  gimp_text_buffer_set_color (editor->buffer, &start, &end, &color);
+}
+
+static void
+gimp_text_style_editor_set_color (GimpTextStyleEditor *editor,
+                                  GtkTextTag          *color_tag)
+{
+  GimpRGB color;
+
+  if (color_tag)
+    gimp_text_tag_get_color (color_tag, &color);
+  else
+    gimp_rgb_set (&color, 0.0, 0.0, 0.0);
+
+  g_signal_handlers_block_by_func (editor->color_button,
+                                   gimp_text_style_editor_color_changed,
+                                   editor);
+
+  gimp_color_button_set_color (GIMP_COLOR_BUTTON (editor->color_button),
+                               &color);
+
+  g_signal_handlers_unblock_by_func (editor->color_button,
+                                     gimp_text_style_editor_color_changed,
+                                     editor);
+}
+
+static void
 gimp_text_style_editor_tag_toggled (GtkToggleButton     *toggle,
                                     GimpTextStyleEditor *editor)
 {
@@ -774,10 +834,12 @@ gimp_text_style_editor_update_idle (GimpTextStyleEditor *editor)
       GList       *list;
       gboolean     any_toggle_active = TRUE;
       gboolean     font_differs      = FALSE;
+      gboolean     color_differs     = FALSE;
       gboolean     size_differs      = FALSE;
       gboolean     baseline_differs  = FALSE;
       gboolean     kerning_differs   = FALSE;
       GtkTextTag  *font_tag          = NULL;
+      GtkTextTag  *color_tag         = NULL;
       GtkTextTag  *size_tag          = NULL;
       GtkTextTag  *baseline_tag      = NULL;
       GtkTextTag  *kerning_tag       = NULL;
@@ -796,6 +858,8 @@ gimp_text_style_editor_update_idle (GimpTextStyleEditor *editor)
       /*  and get some initial values  */
       font_tag     = gimp_text_buffer_get_iter_font (editor->buffer,
                                                      &start, NULL);
+      color_tag    = gimp_text_buffer_get_iter_color (editor->buffer,
+                                                      &start, NULL);
       size_tag     = gimp_text_buffer_get_iter_size (editor->buffer,
                                                      &start, NULL);
       baseline_tag = gimp_text_buffer_get_iter_baseline (editor->buffer,
@@ -839,6 +903,17 @@ gimp_text_style_editor_update_idle (GimpTextStyleEditor *editor)
                 font_differs = TRUE;
             }
 
+          if (! color_differs)
+            {
+              GtkTextTag *tag;
+
+              tag = gimp_text_buffer_get_iter_color (editor->buffer, &iter,
+                                                     NULL);
+
+              if (tag != color_tag)
+                color_differs = TRUE;
+            }
+
           if (! size_differs)
             {
               GtkTextTag *tag;
@@ -881,6 +956,8 @@ gimp_text_style_editor_update_idle (GimpTextStyleEditor *editor)
        }
 
       gimp_text_style_editor_set_font (editor, font_differs ? NULL : font_tag);
+      gimp_text_style_editor_set_color (editor,
+                                        color_differs ? NULL : color_tag);
       gimp_text_style_editor_set_size (editor, size_differs ? NULL : size_tag);
 
       if (baseline_differs)
@@ -924,6 +1001,22 @@ gimp_text_style_editor_update_idle (GimpTextStyleEditor *editor)
       if (! list)
         gimp_text_style_editor_set_font (editor, NULL);
 
+      for (list = editor->buffer->color_tags; list; list = g_list_next (list))
+        {
+          GtkTextTag *tag = list->data;
+
+          if ((g_slist_find (tags, tag) &&
+               ! g_slist_find (tags_on, tag)) ||
+              g_slist_find (tags_off, tag))
+            {
+              gimp_text_style_editor_set_color (editor, tag);
+              break;
+            }
+        }
+
+      if (! list)
+        gimp_text_style_editor_set_color (editor, NULL);
+
       for (list = editor->buffer->size_tags; list; list = g_list_next (list))
         {
           GtkTextTag *tag = list->data;
diff --git a/app/widgets/gimptextstyleeditor.h b/app/widgets/gimptextstyleeditor.h
index 7ce3fd8..46227b6 100644
--- a/app/widgets/gimptextstyleeditor.h
+++ b/app/widgets/gimptextstyleeditor.h
@@ -50,6 +50,8 @@ struct _GimpTextStyleEditor
 
   GtkWidget      *font_entry;
 
+  GtkWidget      *color_button;
+
   GtkWidget      *clear_button;
 
   GtkWidget      *size_spinbutton;
diff --git a/app/widgets/gimptexttag.c b/app/widgets/gimptexttag.c
index 81941c2..5b706af 100644
--- a/app/widgets/gimptexttag.c
+++ b/app/widgets/gimptexttag.c
@@ -22,7 +22,12 @@
 
 #include <gtk/gtk.h>
 
+#include "libgimpcolor/gimpcolor.h"
+
+#include "widgets-types.h"
+
 #include "gimptexttag.h"
+#include "gimpwidgets-utils.h"
 
 
 gint
@@ -74,3 +79,18 @@ gimp_text_tag_get_font (GtkTextTag *tag)
 
   return font;
 }
+
+void
+gimp_text_tag_get_color (GtkTextTag *tag,
+                         GimpRGB    *color)
+{
+  GdkColor *gdk_color;
+
+  g_object_get (tag,
+                GIMP_TEXT_PROP_NAME_COLOR, &gdk_color,
+                NULL);
+
+  gimp_rgb_set_gdk_color (color, gdk_color);
+
+  gdk_color_free (gdk_color);
+}
diff --git a/app/widgets/gimptexttag.h b/app/widgets/gimptexttag.h
index af0c93a..e0c967a 100644
--- a/app/widgets/gimptexttag.h
+++ b/app/widgets/gimptexttag.h
@@ -28,12 +28,15 @@
 #define GIMP_TEXT_PROP_NAME_BASELINE "rise"
 #define GIMP_TEXT_PROP_NAME_KERNING  "rise" /* FIXME */
 #define GIMP_TEXT_PROP_NAME_FONT     "font"
+#define GIMP_TEXT_PROP_NAME_COLOR    "foreground-gdk"
 
 
 gint    gimp_text_tag_get_size     (GtkTextTag *tag);
 gint    gimp_text_tag_get_baseline (GtkTextTag *tag);
 gint    gimp_text_tag_get_kerning  (GtkTextTag *tag);
 gchar * gimp_text_tag_get_font     (GtkTextTag *tag);
+void    gimp_text_tag_get_color    (GtkTextTag *tag,
+                                    GimpRGB    *color);
 
 
 #endif /* __GIMP_TEXT_TAG_H__ */



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