Commit 1e26bb13 authored by Michael Natterer's avatar Michael Natterer 😴
Browse files

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.
parent 8b3592dc
......@@ -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
......
......@@ -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)
{
......
......@@ -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;
}
......
......@@ -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__ */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment