[gimp] app: support baseline changing via Alt+Up and Alt+Down



commit 1e26bb13483b5b76f40ccae445e6e0289898f88f
Author: Michael Natterer <mitch gimp org>
Date:   Sat Feb 27 17:54:36 2010 +0100

    app: support baseline changing via Alt+Up and Alt+Down
    
    Add a list of available baseline tags to GimpTextBuffer and
    automatically create baseline tags as needed. They get serialized as
    <span rise="value">, so add attribute and value parameters to the
    buffer's tag_to_name() and name_to_tag() functions. Properly managing
    the rise's amount is a TODO, currently each keystroke changes the
    baseline by 1024 pango units, which might be whatever depending on the
    output grid.

 app/tools/gimptexttool-editor.c        |   37 ++++++-
 app/widgets/gimptextbuffer-serialize.c |   38 +++++-
 app/widgets/gimptextbuffer.c           |  191 +++++++++++++++++++++++++++++++-
 app/widgets/gimptextbuffer.h           |   74 ++++++++-----
 4 files changed, 299 insertions(+), 41 deletions(-)
---
diff --git a/app/tools/gimptexttool-editor.c b/app/tools/gimptexttool-editor.c
index 9e5c1b5..e200365 100644
--- a/app/tools/gimptexttool-editor.c
+++ b/app/tools/gimptexttool-editor.c
@@ -1034,14 +1034,47 @@ static void
 gimp_text_tool_change_baseline (GimpTextTool *text_tool,
                                 gint          count)
 {
-  g_printerr ("%s: count = %d\n", G_STRFUNC, count);
+  GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer);
+  GtkTextIter    start;
+  GtkTextIter    end;
+
+  if (! gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
+    {
+      gtk_text_buffer_get_iter_at_mark (buffer, &start,
+                                        gtk_text_buffer_get_insert (buffer));
+      gtk_text_buffer_get_end_iter (buffer, &end);
+    }
+
+  gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
+
+  gtk_text_iter_order (&start, &end);
+  gimp_text_buffer_change_baseline (text_tool->buffer, &start, &end,
+                                    count * PANGO_SCALE);
+
+  gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
 }
 
 static void
 gimp_text_tool_change_spacing (GimpTextTool *text_tool,
                                gint          count)
 {
-  g_printerr ("%s: count = %d\n", G_STRFUNC, count);
+  GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer);
+  GtkTextIter    start;
+  GtkTextIter    end;
+
+  if (! gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
+    {
+      gtk_text_buffer_get_iter_at_mark (buffer, &start,
+                                        gtk_text_buffer_get_insert (buffer));
+      gtk_text_buffer_get_end_iter (buffer, &end);
+    }
+
+  gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
+
+  gtk_text_iter_order (&start, &end);
+  gimp_text_buffer_change_spacing (text_tool->buffer, &start, &end, count);
+
+  gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
 }
 
 static void
diff --git a/app/widgets/gimptextbuffer-serialize.c b/app/widgets/gimptextbuffer-serialize.c
index d377ff5..ed57042 100644
--- a/app/widgets/gimptextbuffer-serialize.c
+++ b/app/widgets/gimptextbuffer-serialize.c
@@ -73,11 +73,26 @@ open_tag (GimpTextBuffer *buffer,
           GString        *string,
           GtkTextTag     *tag)
 {
-  const gchar *name = gimp_text_buffer_tag_to_name (buffer, tag);
+  const gchar *name;
+  const gchar *attribute;
+  gchar       *attribute_value;
 
-  if (tag)
+  name = gimp_text_buffer_tag_to_name (buffer, tag,
+                                       &attribute,
+                                       &attribute_value);
+
+  if (name)
     {
-      g_string_append_printf (string, "<%s>", name);
+      if (attribute && attribute_value)
+        {
+          g_string_append_printf (string, "<%s %s=\"%s\">",
+                                  name, attribute, attribute_value);
+          g_free (attribute_value);
+        }
+      else
+        {
+          g_string_append_printf (string, "<%s>", name);
+        }
 
       return TRUE;
     }
@@ -90,9 +105,9 @@ close_tag (GimpTextBuffer *buffer,
            GString        *string,
            GtkTextTag     *tag)
 {
-  const gchar *name = gimp_text_buffer_tag_to_name (buffer, tag);
+  const gchar *name = gimp_text_buffer_tag_to_name (buffer, tag, NULL, NULL);
 
-  if (tag)
+  if (name)
     {
       g_string_append_printf (string, "</%s>", name);
 
@@ -335,14 +350,23 @@ parse_tag_element (GMarkupParseContext  *context,
                    ParseInfo            *info,
                    GError              **error)
 {
-  GtkTextTag *tag;
+  GtkTextTag  *tag;
+  const gchar *attribute_name  = NULL;
+  const gchar *attribute_value = NULL;
 
   g_assert (peek_state (info) == STATE_MARKUP ||
 	    peek_state (info) == STATE_TAG    ||
             peek_state (info) == STATE_UNKNOWN);
 
+  if (attribute_names)
+    attribute_name = attribute_names[0];
+
+  if (attribute_values)
+    attribute_value = attribute_values[0];
+
   tag = gimp_text_buffer_name_to_tag (GIMP_TEXT_BUFFER (info->buffer),
-                                      element_name);
+                                      element_name,
+                                      attribute_name, attribute_value);
 
   if (tag)
     {
diff --git a/app/widgets/gimptextbuffer.c b/app/widgets/gimptextbuffer.c
index 4f07da5..66fecc4 100644
--- a/app/widgets/gimptextbuffer.c
+++ b/app/widgets/gimptextbuffer.c
@@ -20,6 +20,7 @@
 
 #include "config.h"
 
+#include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <string.h>
@@ -146,6 +147,18 @@ gimp_text_buffer_finalize (GObject *object)
 {
   GimpTextBuffer *buffer = GIMP_TEXT_BUFFER (object);
 
+  if (buffer->baseline_tags)
+    {
+      g_list_free (buffer->baseline_tags);
+      buffer->baseline_tags = NULL;
+    }
+
+  if (buffer->spacing_tags)
+    {
+      g_list_free (buffer->spacing_tags);
+      buffer->spacing_tags = NULL;
+    }
+
   gimp_text_buffer_clear_insert_tags (buffer);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -244,13 +257,155 @@ gimp_text_buffer_get_markup (GimpTextBuffer *buffer)
                                               &length);
 }
 
+static gint
+get_baseline_at_iter (GimpTextBuffer     *buffer,
+                      const GtkTextIter  *iter,
+                      GtkTextTag        **baseline_tag)
+{
+  GList *list;
+
+  for (list = buffer->baseline_tags; list; list = g_list_next (list))
+    {
+      GtkTextTag *tag = list->data;
+
+      if (gtk_text_iter_has_tag (iter, tag))
+        {
+          gint baseline;
+
+          *baseline_tag = tag;
+
+          g_object_get (tag,
+                        "rise", &baseline,
+                        NULL);
+
+          return baseline;
+        }
+    }
+
+  *baseline_tag = NULL;
+
+  return 0;
+}
+
+static GtkTextTag *
+get_baseline_tag (GimpTextBuffer *buffer,
+                  gint            baseline)
+{
+  GList      *list;
+  GtkTextTag *tag;
+  gchar       name[32];
+
+  for (list = buffer->baseline_tags; list; list = g_list_next (list))
+    {
+      gint tag_baseline;
+
+      tag = list->data;
+
+      g_object_get (tag,
+                    "rise", &tag_baseline,
+                    NULL);
+
+      if (tag_baseline == baseline)
+        return tag;
+    }
+
+  g_snprintf (name, sizeof (name), "baseline-%d", baseline);
+
+  tag = gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (buffer),
+                                    name,
+                                    "rise", baseline,
+                                    NULL);
+
+  buffer->baseline_tags = g_list_prepend (buffer->baseline_tags, tag);
+
+  return tag;
+}
+
+void
+gimp_text_buffer_change_baseline (GimpTextBuffer    *buffer,
+                                  const GtkTextIter *start,
+                                  const GtkTextIter *end,
+                                  gint               count)
+{
+  GtkTextIter  iter;
+  GtkTextIter  span_start;
+  GtkTextIter  span_end;
+  gint         span_baseline;
+  GtkTextTag  *span_tag;
+
+  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 (&iter, end))
+    return;
+
+  iter          = *start;
+  span_start    = *start;
+  span_baseline = get_baseline_at_iter (buffer, &iter, &span_tag);
+
+  do
+    {
+      gint        iter_baseline;
+      GtkTextTag *iter_tag;
+
+      gtk_text_iter_forward_char (&iter);
+
+      iter_baseline = get_baseline_at_iter (buffer, &iter, &iter_tag);
+
+      span_end = iter;
+
+      if (iter_baseline != span_baseline ||
+          gtk_text_iter_equal (&iter, end))
+        {
+          if (span_baseline != 0)
+            {
+              gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (buffer), span_tag,
+                                          &span_start, &span_end);
+            }
+
+          if (span_baseline + count != 0)
+            {
+              span_tag = get_baseline_tag (buffer, span_baseline + count);
+
+              gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (buffer), span_tag,
+                                         &span_start, &span_end);
+            }
+
+          span_start    = iter;
+          span_baseline = iter_baseline;
+          span_tag      = iter_tag;
+        }
+    }
+  while (! gtk_text_iter_equal (&iter, end));
+}
+
+void
+gimp_text_buffer_change_spacing (GimpTextBuffer    *buffer,
+                                 const GtkTextIter *start,
+                                 const GtkTextIter *end,
+                                 gint               count)
+{
+  g_return_if_fail (GIMP_IS_TEXT_BUFFER (buffer));
+  g_return_if_fail (start != NULL);
+  g_return_if_fail (end != NULL);
+}
+
 const gchar *
-gimp_text_buffer_tag_to_name (GimpTextBuffer *buffer,
-                              GtkTextTag     *tag)
+gimp_text_buffer_tag_to_name (GimpTextBuffer  *buffer,
+                              GtkTextTag      *tag,
+                              const gchar    **attribute,
+                              gchar          **value)
 {
   g_return_val_if_fail (GIMP_IS_TEXT_BUFFER (buffer), NULL);
   g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), NULL);
 
+  if (attribute)
+    *attribute = NULL;
+
+  if (value)
+    *value = NULL;
+
   if (tag == buffer->bold_tag)
     {
       return "b";
@@ -267,13 +422,33 @@ gimp_text_buffer_tag_to_name (GimpTextBuffer *buffer,
     {
       return "s";
     }
+  else if (g_list_find (buffer->baseline_tags, tag))
+    {
+      if (attribute)
+        *attribute = "rise";
+
+      if (value)
+        {
+          gint baseline;
+
+          g_object_get (tag,
+                        "rise", &baseline,
+                        NULL);
+
+          *value = g_strdup_printf ("%d", baseline);
+        }
+
+      return "span";
+    }
 
   return NULL;
 }
 
 GtkTextTag *
 gimp_text_buffer_name_to_tag (GimpTextBuffer *buffer,
-                              const gchar    *name)
+                              const gchar    *name,
+                              const gchar    *attribute,
+                              const gchar    *value)
 {
   g_return_val_if_fail (GIMP_IS_TEXT_BUFFER (buffer), NULL);
   g_return_val_if_fail (name != NULL, NULL);
@@ -294,6 +469,16 @@ gimp_text_buffer_name_to_tag (GimpTextBuffer *buffer,
     {
       return buffer->strikethrough_tag;
     }
+  else if (! strcmp (name, "span"))
+    {
+      if (! attribute || ! value)
+        return NULL;
+
+      if (! strcmp (attribute, "rise"))
+        {
+          return get_baseline_tag (buffer, atoi (value));
+        }
+    }
 
   return NULL;
 }
diff --git a/app/widgets/gimptextbuffer.h b/app/widgets/gimptextbuffer.h
index da69623..a21838f 100644
--- a/app/widgets/gimptextbuffer.h
+++ b/app/widgets/gimptextbuffer.h
@@ -40,6 +40,9 @@ struct _GimpTextBuffer
   GtkTextTag    *underline_tag;
   GtkTextTag    *strikethrough_tag;
 
+  GList         *baseline_tags;
+  GList         *spacing_tags;
+
   GList         *insert_tags;
   gboolean       insert_tags_set;
 
@@ -56,35 +59,48 @@ GType            gimp_text_buffer_get_type          (void) G_GNUC_CONST;
 
 GimpTextBuffer * gimp_text_buffer_new               (void);
 
-void             gimp_text_buffer_set_text          (GimpTextBuffer  *buffer,
-                                                     const gchar     *text);
-gchar          * gimp_text_buffer_get_text          (GimpTextBuffer  *buffer);
-
-void             gimp_text_buffer_set_markup        (GimpTextBuffer  *buffer,
-                                                     const gchar     *markup);
-gchar          * gimp_text_buffer_get_markup        (GimpTextBuffer  *buffer);
-
-const gchar    * gimp_text_buffer_tag_to_name       (GimpTextBuffer  *buffer,
-                                                     GtkTextTag      *tag);
-GtkTextTag     * gimp_text_buffer_name_to_tag       (GimpTextBuffer  *buffer,
-                                                     const gchar     *name);
-
-void             gimp_text_buffer_set_insert_tags   (GimpTextBuffer  *buffer,
-                                                     GList           *style);
-void             gimp_text_buffer_clear_insert_tags (GimpTextBuffer  *buffer);
-void             gimp_text_buffer_insert            (GimpTextBuffer  *buffer,
-                                                     const gchar     *text);
-
-gint             gimp_text_buffer_get_iter_index    (GimpTextBuffer  *buffer,
-                                                     GtkTextIter     *iter);
-
-gboolean         gimp_text_buffer_load              (GimpTextBuffer  *buffer,
-                                                     const gchar     *filename,
-                                                     GError         **error);
-gboolean         gimp_text_buffer_save              (GimpTextBuffer  *buffer,
-                                                     const gchar     *filename,
-                                                     gboolean         selection_only,
-                                                     GError         **error);
+void             gimp_text_buffer_set_text          (GimpTextBuffer    *buffer,
+                                                     const gchar       *text);
+gchar          * gimp_text_buffer_get_text          (GimpTextBuffer    *buffer);
+
+void             gimp_text_buffer_set_markup        (GimpTextBuffer    *buffer,
+                                                     const gchar       *markup);
+gchar          * gimp_text_buffer_get_markup        (GimpTextBuffer    *buffer);
+
+void             gimp_text_buffer_change_baseline   (GimpTextBuffer    *buffer,
+                                                     const GtkTextIter *start,
+                                                     const GtkTextIter *end,
+                                                     gint               count);
+void             gimp_text_buffer_change_spacing    (GimpTextBuffer    *buffer,
+                                                     const GtkTextIter *start,
+                                                     const GtkTextIter *end,
+                                                     gint               count);
+
+const gchar    * gimp_text_buffer_tag_to_name       (GimpTextBuffer    *buffer,
+                                                     GtkTextTag        *tag,
+                                                     const gchar      **attribute,
+                                                     gchar            **value);
+GtkTextTag     * gimp_text_buffer_name_to_tag       (GimpTextBuffer    *buffer,
+                                                     const gchar       *name,
+                                                     const gchar       *attribute,
+                                                     const gchar       *value);
+
+void             gimp_text_buffer_set_insert_tags   (GimpTextBuffer    *buffer,
+                                                     GList             *style);
+void             gimp_text_buffer_clear_insert_tags (GimpTextBuffer    *buffer);
+void             gimp_text_buffer_insert            (GimpTextBuffer    *buffer,
+                                                     const gchar       *text);
+
+gint             gimp_text_buffer_get_iter_index    (GimpTextBuffer    *buffer,
+                                                     GtkTextIter       *iter);
+
+gboolean         gimp_text_buffer_load              (GimpTextBuffer    *buffer,
+                                                     const gchar       *filename,
+                                                     GError           **error);
+gboolean         gimp_text_buffer_save              (GimpTextBuffer    *buffer,
+                                                     const gchar       *filename,
+                                                     gboolean           selection_only,
+                                                     GError           **error);
 
 
 #endif /* __GIMP_TEXT_BUFFER_H__ */



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