summaryrefslogtreecommitdiff
path: root/gtk/gtktextlayout.c
diff options
context:
space:
mode:
authorYevgen Muntyan <muntyan@tamu.edu>2007-11-15 16:24:42 +0000
committerYevgen Muntyan <muntyan@src.gnome.org>2007-11-15 16:24:42 +0000
commita3eb6a98d7a497b1f8bb5a73d497ce673d942837 (patch)
treec1c0bb8ccc35d8426651cf403334767ed1f3d18d /gtk/gtktextlayout.c
parentaa8329533f3eb7ceaa7b03ee0535acf4cff9663e (diff)
downloadgtk+-a3eb6a98d7a497b1f8bb5a73d497ce673d942837.tar.gz
do not call _gtk_text_btree_get_iter_at_line() and
2007-11-15 Yevgen Muntyan <muntyan@tamu.edu> * gtk/gtktextlayout.c: (gtk_text_layout_get_line_display), (get_style): do not call _gtk_text_btree_get_iter_at_line() and _gtk_text_btree_get_tags() for every segment, instead call them once and then collect the tags while iterating over the segments. (get_tags_array_at_iter), (tags_array_toggle_tag): new functions for tags array handling. svn path=/trunk/; revision=18994
Diffstat (limited to 'gtk/gtktextlayout.c')
-rw-r--r--gtk/gtktextlayout.c96
1 files changed, 73 insertions, 23 deletions
diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c
index 8faefef552..0b1b708f8c 100644
--- a/gtk/gtktextlayout.c
+++ b/gtk/gtktextlayout.c
@@ -1166,10 +1166,8 @@ gtk_text_layout_real_wrap (GtkTextLayout *layout,
release_style () to free it. */
static GtkTextAttributes*
get_style (GtkTextLayout *layout,
- const GtkTextIter *iter)
+ GPtrArray *tags)
{
- GtkTextTag** tags;
- gint tag_count = 0;
GtkTextAttributes *style;
/* If we have the one-style cache, then it means
@@ -1184,11 +1182,8 @@ get_style (GtkTextLayout *layout,
g_assert (layout->one_style_cache == NULL);
- /* Get the tags at this spot */
- tags = _gtk_text_btree_get_tags (iter, &tag_count);
-
/* No tags, use default style */
- if (tags == NULL || tag_count == 0)
+ if (tags == NULL || tags->len == 0)
{
/* One ref for the return value, one ref for the
layout->one_style_cache reference */
@@ -1196,24 +1191,17 @@ get_style (GtkTextLayout *layout,
gtk_text_attributes_ref (layout->default_style);
layout->one_style_cache = layout->default_style;
- g_free (tags);
-
return layout->default_style;
}
- /* Sort tags in ascending order of priority */
- _gtk_text_tag_array_sort (tags, tag_count);
-
style = gtk_text_attributes_new ();
gtk_text_attributes_copy_values (layout->default_style,
style);
_gtk_text_attributes_fill_from_tags (style,
- tags,
- tag_count);
-
- g_free (tags);
+ (GtkTextTag**) tags->pdata,
+ tags->len);
g_assert (style->refcount == 1);
@@ -2071,6 +2059,60 @@ update_text_display_cursors (GtkTextLayout *layout,
g_slist_free (cursor_segs);
}
+/* Same as _gtk_text_btree_get_tags(), except it returns GPtrArray,
+ * to be used in gtk_text_layout_get_line_display(). */
+static GPtrArray *
+get_tags_array_at_iter (GtkTextIter *iter)
+{
+ GtkTextTag **tags;
+ GPtrArray *array = NULL;
+ gint n_tags;
+
+ tags = _gtk_text_btree_get_tags (iter, &n_tags);
+
+ if (n_tags > 0)
+ {
+ /* Sort tags in ascending order of priority */
+ _gtk_text_tag_array_sort (tags, n_tags);
+ array = g_ptr_array_sized_new (n_tags);
+ g_ptr_array_set_size (array, n_tags);
+ memcpy (array->pdata, tags, n_tags * sizeof (GtkTextTag*));
+ }
+
+ g_free (tags);
+ return array;
+}
+
+/* Add the tag to the array if it's not there already, and remove
+ * it otherwise. It keeps the array sorted by tags priority. */
+static GPtrArray *
+tags_array_toggle_tag (GPtrArray *array,
+ GtkTextTag *tag)
+{
+ gint pos;
+ GtkTextTag **tags;
+
+ if (array == NULL)
+ array = g_ptr_array_new ();
+
+ tags = (GtkTextTag**) array->pdata;
+
+ for (pos = 0; pos < array->len && tags[pos]->priority < tag->priority; pos++) ;
+
+ if (pos < array->len && tags[pos] == tag)
+ g_ptr_array_remove_index (array, pos);
+ else
+ {
+ g_ptr_array_set_size (array, array->len + 1);
+ if (pos < array->len - 1)
+ memmove (array->pdata + pos + 1, array->pdata + pos,
+ (array->len - pos - 1) * sizeof (GtkTextTag*));
+ array->pdata[pos] = tag;
+ }
+
+ return array;
+}
+
GtkTextLineDisplay *
gtk_text_layout_get_line_display (GtkTextLayout *layout,
GtkTextLine *line,
@@ -2091,6 +2133,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
GSList *tmp_list1, *tmp_list2;
gboolean saw_widget = FALSE;
PangoDirection base_dir;
+ GPtrArray *tags;
+ gboolean initial_toggle_segments;
g_return_val_if_fail (line != NULL, NULL);
@@ -2155,10 +2199,12 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
attrs = pango_attr_list_new ();
- /* Iterate over segments, creating display chunks for them. */
+ /* Iterate over segments, creating display chunks for them, and updating the tags array. */
layout_byte_offset = 0; /* current length of layout text (includes preedit, does not include invisible text) */
buffer_byte_offset = 0; /* position in the buffer line */
seg = _gtk_text_iter_get_any_segment (&iter);
+ tags = get_tags_array_at_iter (&iter);
+ initial_toggle_segments = TRUE;
while (seg != NULL)
{
/* Displayable segments */
@@ -2166,10 +2212,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
seg->type == &gtk_text_pixbuf_type ||
seg->type == &gtk_text_child_type)
{
- _gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
- &iter, line,
- buffer_byte_offset);
- style = get_style (layout, &iter);
+ style = get_style (layout, tags);
+ initial_toggle_segments = FALSE;
/* We have to delay setting the paragraph values until we
* hit the first pixbuf or text segment because toggles at
@@ -2298,6 +2342,10 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
/* Style may have changed, drop our
current cached style */
invalidate_cached_style (layout);
+ /* Add the tag only after we have seen some non-toggle non-mark segment,
+ * otherwise the tag is already accounted for by _gtk_text_btree_get_tags(). */
+ if (!initial_toggle_segments)
+ tags = tags_array_toggle_tag (tags, seg->body.toggle.info->tag);
}
/* Marks */
@@ -2318,7 +2366,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
text_allocated += layout->preedit_len;
text = g_realloc (text, text_allocated);
- style = get_style (layout, &iter);
+ style = get_style (layout, tags);
add_preedit_attrs (layout, style, attrs, layout_byte_offset, size_only);
release_style (layout, style);
@@ -2349,7 +2397,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
if (!para_values_set)
{
- style = get_style (layout, &iter);
+ style = get_style (layout, tags);
set_para_values (layout, base_dir, style, display);
release_style (layout, style);
}
@@ -2426,6 +2474,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
g_free (text);
pango_attr_list_unref (attrs);
+ if (tags != NULL)
+ g_ptr_array_free (tags, TRUE);
layout->one_display_cache = display;