From a3eb6a98d7a497b1f8bb5a73d497ce673d942837 Mon Sep 17 00:00:00 2001 From: Yevgen Muntyan Date: Thu, 15 Nov 2007 16:24:42 +0000 Subject: [PATCH] do not call _gtk_text_btree_get_iter_at_line() and 2007-11-15 Yevgen Muntyan * 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 --- ChangeLog | 9 +++++ gtk/gtktextlayout.c | 96 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 82 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index e766d4cdb8..478650737d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2007-11-15 Yevgen Muntyan + + * 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. + 2007-11-14 Michael Natterer * gtk/gtkmenu.c (gtk_menu_popup): remove recently added 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 == >k_text_pixbuf_type || seg->type == >k_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;