From b0c9b985cba225351e884786a08a321b030413c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 14 Apr 2020 10:09:20 +0200 Subject: layout: Ignore setting the width if it won't have any effect This is a pretty weak check (think e.g. a layout containing the text "a\na"), but it's very easy to do and still hits quite a few cases in real-world applications. --- pango/pango-layout.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 44d59367..872ccd71 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -362,6 +362,11 @@ pango_layout_set_width (PangoLayout *layout, if (width != layout->width) { layout->width = width; + + /* Increasing the width can only decrease the line count */ + if (layout->line_count == 1 && width > layout->width) + return; + layout_changed (layout); } } -- cgit v1.2.1 From 993ac0ad925e8a22e41591390d069d7ecf37518b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 14 Apr 2020 10:49:49 +0200 Subject: pangocairo-context: Don't invalidate if font options are equal --- pango/pangocairo-context.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pango/pangocairo-context.c b/pango/pangocairo-context.c index 5949c448..959fcfe0 100644 --- a/pango/pangocairo-context.c +++ b/pango/pangocairo-context.c @@ -242,7 +242,15 @@ pango_cairo_context_set_font_options (PangoContext *context, g_return_if_fail (PANGO_IS_CONTEXT (context)); - info = get_context_info (context, TRUE); + info = get_context_info (context, TRUE); + + if (!info->set_options && !options) + return; + + if (info->set_options && + options && + cairo_font_options_equal (info->set_options, options)) + return; if (info->set_options || options) pango_context_changed (context); -- cgit v1.2.1 From 03774a47fda0231fae38f44e68e05deaf9ca95dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 14 Apr 2020 17:43:35 +0200 Subject: layout: Try to avoid some work when creating iters Instead of getting the logical rect and then not using it, try not to compute it in the first place. --- pango/pango-layout.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 872ccd71..ee754835 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -6183,7 +6183,6 @@ _pango_layout_get_iter (PangoLayout *layout, PangoLayoutIter*iter) { int run_start_index; - PangoRectangle logical_rect; g_return_if_fail (PANGO_IS_LAYOUT (layout)); @@ -6207,11 +6206,25 @@ _pango_layout_get_iter (PangoLayout *layout, iter->run = NULL; iter->line_extents = NULL; - pango_layout_get_extents_internal (layout, - NULL, - &logical_rect, - &iter->line_extents); - iter->layout_width = layout->width == -1 ? logical_rect.width : layout->width; + + if (layout->width == -1) + { + PangoRectangle logical_rect; + + pango_layout_get_extents_internal (layout, + NULL, + &logical_rect, + &iter->line_extents); + iter->layout_width = logical_rect.width; + } + else + { + pango_layout_get_extents_internal (layout, + NULL, + NULL, + &iter->line_extents); + iter->layout_width = layout->width; + } iter->line_index = 0; update_run (iter, run_start_index); -- cgit v1.2.1 From 99431a5ce902ec6410ca4e73d49df8127405a97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 15 Apr 2020 09:00:32 +0200 Subject: Allocate internal PangoAttrListIterators on the stack --- pango/pango-attributes-private.h | 37 +++++++++++++++++++++++++ pango/pango-attributes.c | 40 +++++++++++++++------------ pango/pango-layout.c | 60 +++++++++++++++++++++------------------- 3 files changed, 91 insertions(+), 46 deletions(-) create mode 100644 pango/pango-attributes-private.h diff --git a/pango/pango-attributes-private.h b/pango/pango-attributes-private.h new file mode 100644 index 00000000..38e4525d --- /dev/null +++ b/pango/pango-attributes-private.h @@ -0,0 +1,37 @@ +/* Pango + * pango-attributes-private.h: Internal structures of PangoLayout + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __PANGO_ATTRIBUTES_PRIVATE_H__ +#define __PANGO_ATTRIBUTES_PRIVATE_H__ + +struct _PangoAttrIterator +{ + GSList *next_attribute; + GList *attribute_stack; + guint start_index; + guint end_index; +}; + +void _pango_attr_list_get_iterator (PangoAttrList *list, + PangoAttrIterator *iterator); + +void _pango_attr_iterator_destroy (PangoAttrIterator *iterator); + + +#endif diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c index 03a45de4..98e26872 100644 --- a/pango/pango-attributes.c +++ b/pango/pango-attributes.c @@ -34,6 +34,7 @@ #include #include "pango-attributes.h" +#include "pango-attributes-private.h" #include "pango-impl-utils.h" struct _PangoAttrList @@ -43,14 +44,6 @@ struct _PangoAttrList GSList *attributes_tail; }; -struct _PangoAttrIterator -{ - GSList *next_attribute; - GList *attribute_stack; - guint start_index; - guint end_index; -}; - static PangoAttribute *pango_attr_color_new (const PangoAttrClass *klass, guint16 red, guint16 green, @@ -1997,6 +1990,20 @@ G_DEFINE_BOXED_TYPE (PangoAttrIterator, pango_attr_iterator_copy, pango_attr_iterator_destroy) +void +_pango_attr_list_get_iterator (PangoAttrList *list, + PangoAttrIterator *iterator) +{ + iterator->next_attribute = list->attributes; + iterator->attribute_stack = NULL; + + iterator->start_index = 0; + iterator->end_index = 0; + + if (!pango_attr_iterator_next (iterator)) + iterator->end_index = G_MAXUINT; +} + /** * pango_attr_list_get_iterator: * @list: a #PangoAttrList @@ -2015,14 +2022,7 @@ pango_attr_list_get_iterator (PangoAttrList *list) g_return_val_if_fail (list != NULL, NULL); iterator = g_slice_new (PangoAttrIterator); - iterator->next_attribute = list->attributes; - iterator->attribute_stack = NULL; - - iterator->start_index = 0; - iterator->end_index = 0; - - if (!pango_attr_iterator_next (iterator)) - iterator->end_index = G_MAXUINT; + _pango_attr_list_get_iterator (list, iterator); return iterator; } @@ -2135,6 +2135,12 @@ pango_attr_iterator_copy (PangoAttrIterator *iterator) return copy; } +void +_pango_attr_iterator_destroy (PangoAttrIterator *iterator) +{ + g_list_free (iterator->attribute_stack); +} + /** * pango_attr_iterator_destroy: * @iterator: a #PangoAttrIterator. @@ -2146,7 +2152,7 @@ pango_attr_iterator_destroy (PangoAttrIterator *iterator) { g_return_if_fail (iterator != NULL); - g_list_free (iterator->attribute_stack); + _pango_attr_iterator_destroy (iterator); g_slice_free (PangoAttrIterator, iterator); } diff --git a/pango/pango-layout.c b/pango/pango-layout.c index ee754835..24b492fe 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -78,6 +78,7 @@ #include #include "pango-layout-private.h" +#include "pango-attributes-private.h" typedef struct _ItemProperties ItemProperties; @@ -2929,7 +2930,8 @@ pango_layout_get_pixel_size (PangoLayout *layout, { PangoRectangle logical_rect; - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + pango_layout_get_extents_internal (layout, NULL, &logical_rect, NULL); + pango_extents_to_pixels (&logical_rect, NULL); if (width) *width = logical_rect.width; @@ -3063,13 +3065,13 @@ ensure_tab_width (PangoLayout *layout) PangoAttribute *attr; PangoAttrList *layout_attrs; PangoAttrList *tmp_attrs; - PangoAttrIterator *iter; + PangoAttrIterator iter; PangoFontDescription *font_desc = pango_font_description_copy_static (pango_context_get_font_description (layout->context)); PangoLanguage *language; layout_attrs = pango_layout_get_effective_attributes (layout); - iter = pango_attr_list_get_iterator (layout_attrs); - pango_attr_iterator_get_font (iter, font_desc, &language, NULL); + _pango_attr_list_get_iterator (layout_attrs, &iter); + pango_attr_iterator_get_font (&iter, font_desc, &language, NULL); tmp_attrs = pango_attr_list_new (); @@ -3085,7 +3087,7 @@ ensure_tab_width (PangoLayout *layout) items = pango_itemize (layout->context, " ", 0, 1, tmp_attrs, NULL); - pango_attr_iterator_destroy (iter); + _pango_attr_iterator_destroy (&iter); if (layout_attrs != layout->attrs) { pango_attr_list_unref (layout_attrs); @@ -3460,7 +3462,7 @@ get_need_hyphen (PangoItem *item, gboolean prev_space; gboolean prev_hyphen; PangoAttrList *attrs; - PangoAttrIterator *iter; + PangoAttrIterator iter; GSList *l; attrs = pango_attr_list_new (); @@ -3470,7 +3472,7 @@ get_need_hyphen (PangoItem *item, if (attr->klass->type == PANGO_ATTR_INSERT_HYPHENS) pango_attr_list_change (attrs, pango_attribute_copy (attr)); } - iter = pango_attr_list_get_iterator (attrs); + _pango_attr_list_get_iterator (attrs, &iter); for (i = 0, p = text + item->offset; i < item->num_chars; i++, p = g_utf8_next_char (p)) { @@ -3482,15 +3484,15 @@ get_need_hyphen (PangoItem *item, pos = p - text; do { - pango_attr_iterator_range (iter, &start, &end); + pango_attr_iterator_range (&iter, &start, &end); if (end > pos) break; - } while (pango_attr_iterator_next (iter)); + } while (pango_attr_iterator_next (&iter)); if (start <= pos && pos < end) { PangoAttribute *attr; - attr = pango_attr_iterator_get (iter, PANGO_ATTR_INSERT_HYPHENS); + attr = pango_attr_iterator_get (&iter, PANGO_ATTR_INSERT_HYPHENS); if (attr) insert_hyphens = ((PangoAttrInt*)attr)->value; @@ -3555,7 +3557,7 @@ get_need_hyphen (PangoItem *item, prev_hyphen = hyphen; } - pango_attr_iterator_destroy (iter); + _pango_attr_iterator_destroy (&iter); pango_attr_list_unref (attrs); } @@ -4158,20 +4160,20 @@ apply_attributes_to_items (GList *items, PangoAttrList *attrs) { GList *l; - PangoAttrIterator *iter; + PangoAttrIterator iter; if (!attrs) return; - iter = pango_attr_list_get_iterator (attrs); + _pango_attr_list_get_iterator (attrs, &iter); for (l = items; l; l = l->next) { PangoItem *item = l->data; - pango_item_apply_attrs (item, iter); + pango_item_apply_attrs (item, &iter); } - pango_attr_iterator_destroy (iter); + _pango_attr_iterator_destroy (&iter); } static void @@ -4218,7 +4220,7 @@ pango_layout_check_lines (PangoLayout *layout) PangoAttrList *attrs; PangoAttrList *itemize_attrs; PangoAttrList *shape_attrs; - PangoAttrIterator *iter; + PangoAttrIterator iter; PangoDirection prev_base_dir = PANGO_DIRECTION_NEUTRAL, base_dir = PANGO_DIRECTION_NEUTRAL; ParaBreakState state; @@ -4240,9 +4242,7 @@ pango_layout_check_lines (PangoLayout *layout) shape_attrs = pango_attr_list_filter (attrs, affects_break_or_shape, NULL); itemize_attrs = pango_attr_list_filter (attrs, affects_itemization, NULL); if (itemize_attrs) - iter = pango_attr_list_get_iterator (itemize_attrs); - else - iter = NULL; + _pango_attr_list_get_iterator (itemize_attrs, &iter); layout->log_attrs = g_new (PangoLogAttr, layout->n_chars + 1); @@ -4320,7 +4320,7 @@ pango_layout_check_lines (PangoLayout *layout) start - layout->text, end - start, itemize_attrs, - iter); + itemize_attrs ? &iter : NULL); apply_attributes_to_items (state.items, shape_attrs); @@ -4377,11 +4377,11 @@ pango_layout_check_lines (PangoLayout *layout) apply_attributes_to_runs (layout, attrs); layout->lines = g_slist_reverse (layout->lines); - if (iter) - pango_attr_iterator_destroy (iter); - if (itemize_attrs) - pango_attr_list_unref (itemize_attrs); + { + pango_attr_list_unref (itemize_attrs); + _pango_attr_iterator_destroy (&iter); + } if (shape_attrs) pango_attr_list_unref (shape_attrs); @@ -4841,12 +4841,14 @@ pango_layout_get_empty_extents_at_index (PangoLayout *layout, */ if (layout->attrs) { - PangoAttrIterator *iter = pango_attr_list_get_iterator (layout->attrs); + PangoAttrIterator iter; int start, end; + _pango_attr_list_get_iterator (layout->attrs, &iter); + do { - pango_attr_iterator_range (iter, &start, &end); + pango_attr_iterator_range (&iter, &start, &end); if (start <= index && index < end) { @@ -4856,7 +4858,7 @@ pango_layout_get_empty_extents_at_index (PangoLayout *layout, free_font_desc = TRUE; } - pango_attr_iterator_get_font (iter, + pango_attr_iterator_get_font (&iter, font_desc, NULL, NULL); @@ -4865,9 +4867,9 @@ pango_layout_get_empty_extents_at_index (PangoLayout *layout, } } - while (pango_attr_iterator_next (iter)); + while (pango_attr_iterator_next (&iter)); - pango_attr_iterator_destroy (iter); + _pango_attr_iterator_destroy (&iter); } font = pango_context_load_font (layout->context, font_desc); -- cgit v1.2.1 From 62fd1b58c79e11077ac8b03c2eeaae3cec84e976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 15 Apr 2020 15:14:47 +0200 Subject: layotu: Avoid invalidating when setting attrs from NULL to NULL --- pango/pango-layout.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 24b492fe..7a25494b 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -679,11 +679,15 @@ pango_layout_get_line_spacing (PangoLayout *layout) **/ void pango_layout_set_attributes (PangoLayout *layout, - PangoAttrList *attrs) + PangoAttrList *attrs) { PangoAttrList *old_attrs; + g_return_if_fail (layout != NULL); + if (!attrs && !layout->attrs) + return; + old_attrs = layout->attrs; /* We always clear lines such that this function can be called -- cgit v1.2.1 From 25049ad1e41ad9127366e10c4c06ec56b5ffa69a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 15 Apr 2020 15:15:35 +0200 Subject: layout: Add missing (nullable) annotation --- pango/pango-layout.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 7a25494b..09132a45 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -711,7 +711,8 @@ pango_layout_set_attributes (PangoLayout *layout, * * Gets the attribute list for the layout, if any. * - * Return value: (transfer none): a #PangoAttrList. + * Return value: (transfer none) (nullable): a #PangoAttrList or %NULL + * if none was set. **/ PangoAttrList* pango_layout_get_attributes (PangoLayout *layout) -- cgit v1.2.1 From c802c85d0ed07cc1dae5db8f1991d82ec45bf1bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 15 Apr 2020 15:37:38 +0200 Subject: Allocate internal PangoAttrLists on the stack --- pango/break.c | 21 +++++++++-------- pango/ellipsize.c | 15 +++++++----- pango/pango-attributes-private.h | 9 ++++++++ pango/pango-attributes.c | 50 ++++++++++++++++++++++------------------ pango/pango-layout.c | 22 +++++++++--------- 5 files changed, 67 insertions(+), 50 deletions(-) diff --git a/pango/break.c b/pango/break.c index 875d776c..432ff493 100644 --- a/pango/break.c +++ b/pango/break.c @@ -24,6 +24,7 @@ #include "pango-break.h" #include "pango-script-private.h" #include "pango-emoji-private.h" +#include "pango-attributes-private.h" #include "pango-break-table.h" #include "pango-impl-utils.h" #include @@ -1905,31 +1906,31 @@ break_attrs (const char *text, PangoLogAttr *log_attrs, int log_attrs_len) { - PangoAttrList *list; - PangoAttrIterator *iter; + PangoAttrList list; + PangoAttrIterator iter; GSList *l; - list = pango_attr_list_new (); + _pango_attr_list_init (&list); for (l = attributes; l; l = l->next) { PangoAttribute *attr = l->data; if (attr->klass->type == PANGO_ATTR_ALLOW_BREAKS) - pango_attr_list_insert (list, pango_attribute_copy (attr)); + pango_attr_list_insert (&list, pango_attribute_copy (attr)); } - iter = pango_attr_list_get_iterator (list); + _pango_attr_list_get_iterator (&list, &iter); do { PangoAttribute *attr; - attr = pango_attr_iterator_get (iter, PANGO_ATTR_ALLOW_BREAKS); + attr = pango_attr_iterator_get (&iter, PANGO_ATTR_ALLOW_BREAKS); if (attr && ((PangoAttrInt*)attr)->value == 0) { int start, end; int start_pos, end_pos; int pos; - pango_attr_iterator_range (iter, &start, &end); + pango_attr_iterator_range (&iter, &start, &end); if (start < offset) start_pos = 0; else @@ -1946,10 +1947,10 @@ break_attrs (const char *text, log_attrs[pos].is_char_break = FALSE; } } - } while (pango_attr_iterator_next (iter)); + } while (pango_attr_iterator_next (&iter)); - pango_attr_iterator_destroy (iter); - pango_attr_list_unref (list); + _pango_attr_iterator_destroy (&iter); + _pango_attr_list_destroy (&list); return TRUE; } diff --git a/pango/ellipsize.c b/pango/ellipsize.c index 4b27025e..4eb98a1a 100644 --- a/pango/ellipsize.c +++ b/pango/ellipsize.c @@ -25,6 +25,7 @@ #include "pango-glyph-item.h" #include "pango-layout-private.h" #include "pango-font-private.h" +#include "pango-attributes-private.h" #include "pango-impl-utils.h" typedef struct _EllipsizeState EllipsizeState; @@ -299,7 +300,7 @@ itemize_text (EllipsizeState *state, static void shape_ellipsis (EllipsizeState *state) { - PangoAttrList *attrs = pango_attr_list_new (); + PangoAttrList attrs; GSList *run_attrs; PangoItem *item; PangoGlyphString *glyphs; @@ -309,6 +310,8 @@ shape_ellipsis (EllipsizeState *state) int len; int i; + _pango_attr_list_init (&attrs); + /* Create/reset state->ellipsis_run */ if (!state->ellipsis_run) @@ -333,7 +336,7 @@ shape_ellipsis (EllipsizeState *state) attr->start_index = 0; attr->end_index = G_MAXINT; - pango_attr_list_insert (attrs, attr); + pango_attr_list_insert (&attrs, attr); } g_slist_free (run_attrs); @@ -341,7 +344,7 @@ shape_ellipsis (EllipsizeState *state) fallback = pango_attr_fallback_new (FALSE); fallback->start_index = 0; fallback->end_index = G_MAXINT; - pango_attr_list_insert (attrs, fallback); + pango_attr_list_insert (&attrs, fallback); /* First try using a specific ellipsis character in the best matching font */ @@ -350,7 +353,7 @@ shape_ellipsis (EllipsizeState *state) else ellipsis_text = "\342\200\246"; /* U+2026: HORIZONTAL ELLIPSIS */ - item = itemize_text (state, ellipsis_text, attrs); + item = itemize_text (state, ellipsis_text, &attrs); /* If that fails we use "..." in the first matching font */ @@ -365,10 +368,10 @@ shape_ellipsis (EllipsizeState *state) ((PangoAttrInt *)fallback)->value = TRUE; ellipsis_text = "..."; - item = itemize_text (state, ellipsis_text, attrs); + item = itemize_text (state, ellipsis_text, &attrs); } - pango_attr_list_unref (attrs); + _pango_attr_list_destroy (&attrs); state->ellipsis_run->item = item; diff --git a/pango/pango-attributes-private.h b/pango/pango-attributes-private.h index 38e4525d..efeb88cd 100644 --- a/pango/pango-attributes-private.h +++ b/pango/pango-attributes-private.h @@ -28,6 +28,15 @@ struct _PangoAttrIterator guint end_index; }; +struct _PangoAttrList +{ + guint ref_count; + GSList *attributes; + GSList *attributes_tail; +}; + +void _pango_attr_list_init (PangoAttrList *list); +void _pango_attr_list_destroy (PangoAttrList *list); void _pango_attr_list_get_iterator (PangoAttrList *list, PangoAttrIterator *iterator); diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c index 98e26872..5ac955c4 100644 --- a/pango/pango-attributes.c +++ b/pango/pango-attributes.c @@ -37,13 +37,6 @@ #include "pango-attributes-private.h" #include "pango-impl-utils.h" -struct _PangoAttrList -{ - guint ref_count; - GSList *attributes; - GSList *attributes_tail; -}; - static PangoAttribute *pango_attr_color_new (const PangoAttrClass *klass, guint16 red, guint16 green, @@ -1313,6 +1306,14 @@ G_DEFINE_BOXED_TYPE (PangoAttrList, pango_attr_list, pango_attr_list_copy, pango_attr_list_unref); +void +_pango_attr_list_init (PangoAttrList *list) +{ + list->ref_count = 1; + list->attributes = NULL; + list->attributes_tail = NULL; +} + /** * pango_attr_list_new: * @@ -1326,9 +1327,7 @@ pango_attr_list_new (void) { PangoAttrList *list = g_slice_new (PangoAttrList); - list->ref_count = 1; - list->attributes = NULL; - list->attributes_tail = NULL; + _pango_attr_list_init (list); return list; } @@ -1354,6 +1353,23 @@ pango_attr_list_ref (PangoAttrList *list) return list; } +void +_pango_attr_list_destroy (PangoAttrList *list) +{ + GSList *tmp_list; + + tmp_list = list->attributes; + while (tmp_list) + { + PangoAttribute *attr = tmp_list->data; + tmp_list = tmp_list->next; + + attr->klass->destroy (attr); + } + + g_slist_free (list->attributes); +} + /** * pango_attr_list_unref: * @list: (nullable): a #PangoAttrList, may be %NULL @@ -1365,8 +1381,6 @@ pango_attr_list_ref (PangoAttrList *list) void pango_attr_list_unref (PangoAttrList *list) { - GSList *tmp_list; - if (list == NULL) return; @@ -1374,17 +1388,7 @@ pango_attr_list_unref (PangoAttrList *list) if (g_atomic_int_dec_and_test ((int *) &list->ref_count)) { - tmp_list = list->attributes; - while (tmp_list) - { - PangoAttribute *attr = tmp_list->data; - tmp_list = tmp_list->next; - - attr->klass->destroy (attr); - } - - g_slist_free (list->attributes); - + _pango_attr_list_destroy (list); g_slice_free (PangoAttrList, list); } } diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 09132a45..f6d37068 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -3069,7 +3069,7 @@ ensure_tab_width (PangoLayout *layout) GList *items; PangoAttribute *attr; PangoAttrList *layout_attrs; - PangoAttrList *tmp_attrs; + PangoAttrList tmp_attrs; PangoAttrIterator iter; PangoFontDescription *font_desc = pango_font_description_copy_static (pango_context_get_font_description (layout->context)); PangoLanguage *language; @@ -3078,19 +3078,19 @@ ensure_tab_width (PangoLayout *layout) _pango_attr_list_get_iterator (layout_attrs, &iter); pango_attr_iterator_get_font (&iter, font_desc, &language, NULL); - tmp_attrs = pango_attr_list_new (); + _pango_attr_list_init (&tmp_attrs); attr = pango_attr_font_desc_new (font_desc); pango_font_description_free (font_desc); - pango_attr_list_insert_before (tmp_attrs, attr); + pango_attr_list_insert_before (&tmp_attrs, attr); if (language) { attr = pango_attr_language_new (language); - pango_attr_list_insert_before (tmp_attrs, attr); + pango_attr_list_insert_before (&tmp_attrs, attr); } - items = pango_itemize (layout->context, " ", 0, 1, tmp_attrs, NULL); + items = pango_itemize (layout->context, " ", 0, 1, &tmp_attrs, NULL); _pango_attr_iterator_destroy (&iter); if (layout_attrs != layout->attrs) @@ -3098,7 +3098,7 @@ ensure_tab_width (PangoLayout *layout) pango_attr_list_unref (layout_attrs); layout_attrs = NULL; } - pango_attr_list_unref (tmp_attrs); + _pango_attr_list_destroy (&tmp_attrs); item = items->data; pango_shape (" ", 8, &item->analysis, glyphs); @@ -3466,18 +3466,18 @@ get_need_hyphen (PangoItem *item, const char *p; gboolean prev_space; gboolean prev_hyphen; - PangoAttrList *attrs; + PangoAttrList attrs; PangoAttrIterator iter; GSList *l; - attrs = pango_attr_list_new (); + _pango_attr_list_init (&attrs); for (l = item->analysis.extra_attrs; l; l = l->next) { PangoAttribute *attr = l->data; if (attr->klass->type == PANGO_ATTR_INSERT_HYPHENS) - pango_attr_list_change (attrs, pango_attribute_copy (attr)); + pango_attr_list_change (&attrs, pango_attribute_copy (attr)); } - _pango_attr_list_get_iterator (attrs, &iter); + _pango_attr_list_get_iterator (&attrs, &iter); for (i = 0, p = text + item->offset; i < item->num_chars; i++, p = g_utf8_next_char (p)) { @@ -3563,7 +3563,7 @@ get_need_hyphen (PangoItem *item, } _pango_attr_iterator_destroy (&iter); - pango_attr_list_unref (attrs); + _pango_attr_list_destroy (&attrs); } static gboolean -- cgit v1.2.1 From 0efa31306ce04b3b3a6c8e2da96af32834ac860a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 17 Apr 2020 07:17:43 +0200 Subject: layout: Avoid getting the text length if we know it already --- pango/pango-layout.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/pango/pango-layout.c b/pango/pango-layout.c index f6d37068..2de3f9eb 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -1125,15 +1125,22 @@ pango_layout_set_text (PangoLayout *layout, old_text = layout->text; if (length < 0) - layout->text = g_strdup (text); + { + layout->length = strlen (text); + layout->text = g_strndup (text, layout->length); + } else if (length > 0) - /* This is not exactly what we want. We don't need the padding... - */ - layout->text = g_strndup (text, length); + { + /* This is not exactly what we want. We don't need the padding... + */ + layout->length = length; + layout->text = g_strndup (text, length); + } else - layout->text = g_malloc0 (1); - - layout->length = strlen (layout->text); + { + layout->length = 0; + layout->text = g_malloc0 (1); + } /* validate it, and replace invalid bytes with -1 */ start = layout->text; -- cgit v1.2.1 From a79e38a784430af97c6b9423f63fc89f90482da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 17 Apr 2020 08:21:36 +0200 Subject: attributes: Add _pango_attr_list_has_attributes A private function to find empty attribute lists --- pango/pango-attributes-private.h | 2 ++ pango/pango-attributes.c | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/pango/pango-attributes-private.h b/pango/pango-attributes-private.h index efeb88cd..b913cc2f 100644 --- a/pango/pango-attributes-private.h +++ b/pango/pango-attributes-private.h @@ -37,6 +37,8 @@ struct _PangoAttrList void _pango_attr_list_init (PangoAttrList *list); void _pango_attr_list_destroy (PangoAttrList *list); +gboolean _pango_attr_list_has_attributes (const PangoAttrList *list); + void _pango_attr_list_get_iterator (PangoAttrList *list, PangoAttrIterator *iterator); diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c index 5ac955c4..84d24838 100644 --- a/pango/pango-attributes.c +++ b/pango/pango-attributes.c @@ -1989,6 +1989,12 @@ pango_attr_list_equal (PangoAttrList *list, return TRUE; } +gboolean +_pango_attr_list_has_attributes (const PangoAttrList *list) +{ + return (list->attributes != NULL); +} + G_DEFINE_BOXED_TYPE (PangoAttrIterator, pango_attr_iterator, pango_attr_iterator_copy, -- cgit v1.2.1 From cc5b6c7af26bbeb7862a978606ed4ac17b82c233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 17 Apr 2020 08:22:04 +0200 Subject: break_attrs: Bail out if we have no ALLOW_BREAKS attributes --- pango/break.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pango/break.c b/pango/break.c index 432ff493..2f5ff02e 100644 --- a/pango/break.c +++ b/pango/break.c @@ -1919,6 +1919,12 @@ break_attrs (const char *text, pango_attr_list_insert (&list, pango_attribute_copy (attr)); } + if (!_pango_attr_list_has_attributes (&list)) + { + _pango_attr_list_destroy (&list); + return FALSE; + } + _pango_attr_list_get_iterator (&list, &iter); do { PangoAttribute *attr; -- cgit v1.2.1 From 17248221740fa476986248f8103a333b0e23db49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 17 Apr 2020 08:33:55 +0200 Subject: break: Make a local const Make it clearer that we're not going to modify the attribute --- pango/break.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pango/break.c b/pango/break.c index 2f5ff02e..26a79873 100644 --- a/pango/break.c +++ b/pango/break.c @@ -1927,9 +1927,8 @@ break_attrs (const char *text, _pango_attr_list_get_iterator (&list, &iter); do { - PangoAttribute *attr; + const PangoAttribute *attr = pango_attr_iterator_get (&iter, PANGO_ATTR_ALLOW_BREAKS); - attr = pango_attr_iterator_get (&iter, PANGO_ATTR_ALLOW_BREAKS); if (attr && ((PangoAttrInt*)attr)->value == 0) { int start, end; -- cgit v1.2.1 From 4289a208b8b1a67fb732c9f44e5eef0825f8c430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 17 Apr 2020 08:34:27 +0200 Subject: break: Only call break_attrs if we really have attributes --- pango/break.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pango/break.c b/pango/break.c index 26a79873..58bf2f90 100644 --- a/pango/break.c +++ b/pango/break.c @@ -1597,7 +1597,7 @@ tailor_break (const char *text, res = break_script (text, length, analysis, attrs, attrs_len); - if (item_offset >= 0) + if (item_offset >= 0 && analysis->extra_attrs) res |= break_attrs (text, length, analysis->extra_attrs, item_offset, attrs, attrs_len); return res; -- cgit v1.2.1 From fd7e209ce6c52a6213fe1438c80709bc39ea6695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 17 Apr 2020 09:32:32 +0200 Subject: glyph-item: Allocate attr iterator on the stack --- pango/pango-glyph-item.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/pango/pango-glyph-item.c b/pango/pango-glyph-item.c index eb880608..326ae37f 100644 --- a/pango/pango-glyph-item.c +++ b/pango/pango-glyph-item.c @@ -24,6 +24,7 @@ #include "pango-glyph-item.h" #include "pango-impl-utils.h" +#include "pango-attributes-private.h" #define LTR(glyph_item) (((glyph_item)->item->analysis.level % 2) == 0) @@ -584,7 +585,7 @@ pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, const char *text, PangoAttrList *list) { - PangoAttrIterator *iter = pango_attr_list_get_iterator (list); + PangoAttrIterator iter; GSList *result = NULL; ApplyAttrsState state; gboolean start_new_segment = FALSE; @@ -607,15 +608,16 @@ pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, /* Advance the attr iterator to the start of the item */ + _pango_attr_list_get_iterator (list, &iter); do { - pango_attr_iterator_range (iter, &range_start, &range_end); + pango_attr_iterator_range (&iter, &range_start, &range_end); if (range_end > glyph_item->item->offset) break; } - while (pango_attr_iterator_next (iter)); + while (pango_attr_iterator_next (&iter)); - state.segment_attrs = pango_attr_iterator_get_attrs (iter); + state.segment_attrs = pango_attr_iterator_get_attrs (&iter); is_ellipsis = (glyph_item->item->analysis.flags & PANGO_ANALYSIS_FLAG_IS_ELLIPSIS) != 0; @@ -644,7 +646,7 @@ pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, { result = g_slist_prepend (result, split_before_cluster_start (&state)); - state.segment_attrs = pango_attr_iterator_get_attrs (iter); + state.segment_attrs = pango_attr_iterator_get_attrs (&iter); } start_new_segment = FALSE; @@ -663,8 +665,8 @@ pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, */ start_new_segment = TRUE; - have_next = pango_attr_iterator_next (iter); - pango_attr_iterator_range (iter, &range_start, &range_end); + have_next = pango_attr_iterator_next (&iter); + pango_attr_iterator_range (&iter, &range_start, &range_end); if (range_start >= state.iter.end_index) /* New range doesn't intersect this cluster */ { @@ -688,7 +690,7 @@ pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, } state.segment_attrs = g_slist_concat (state.segment_attrs, - pango_attr_iterator_get_attrs (iter)); + pango_attr_iterator_get_attrs (&iter)); } while (have_next); } @@ -702,7 +704,7 @@ pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, if (LTR (glyph_item)) result = g_slist_reverse (result); - pango_attr_iterator_destroy (iter); + _pango_attr_iterator_destroy (&iter); return result; } -- cgit v1.2.1 From 4d658d4c19fb22126b0f848a5b018227747bfd07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 17 Apr 2020 10:20:28 +0200 Subject: testattributes: Properly free GString Not needed afterwards. --- tests/testattributes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testattributes.c b/tests/testattributes.c index 9964f3d0..eaca6663 100644 --- a/tests/testattributes.c +++ b/tests/testattributes.c @@ -100,7 +100,7 @@ assert_attributes (GSList *attrs, s = g_string_new (""); print_attributes (attrs, s); g_assert_cmpstr (s->str, ==, expected); - g_string_free (s, FALSE); + g_string_free (s, TRUE); } static void -- cgit v1.2.1 From c1943bd42fb4390a133dce0e2ec80da7306ba79c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 17 Apr 2020 19:57:26 +0200 Subject: pango-layout: Try to avoid allocating a new PangoAttrList --- pango/pango-layout.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 2de3f9eb..07a32664 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -4102,17 +4102,25 @@ pango_layout_get_effective_attributes (PangoLayout *layout) if (layout->attrs) attrs = pango_attr_list_copy (layout->attrs); else - attrs = pango_attr_list_new (); + attrs = NULL; if (layout->font_desc) { PangoAttribute *attr = pango_attr_font_desc_new (layout->font_desc); + + if (!attrs) + attrs = pango_attr_list_new (); + pango_attr_list_insert_before (attrs, attr); } if (layout->single_paragraph) { PangoAttribute *attr = pango_attr_show_new (PANGO_SHOW_LINE_BREAKS); + + if (!attrs) + attrs = pango_attr_list_new (); + pango_attr_list_insert_before (attrs, attr); } @@ -4250,11 +4258,19 @@ pango_layout_check_lines (PangoLayout *layout) pango_layout_set_text (layout, NULL, 0); attrs = pango_layout_get_effective_attributes (layout); + if (attrs) + { + shape_attrs = pango_attr_list_filter (attrs, affects_break_or_shape, NULL); + itemize_attrs = pango_attr_list_filter (attrs, affects_itemization, NULL); - shape_attrs = pango_attr_list_filter (attrs, affects_break_or_shape, NULL); - itemize_attrs = pango_attr_list_filter (attrs, affects_itemization, NULL); - if (itemize_attrs) - _pango_attr_list_get_iterator (itemize_attrs, &iter); + if (itemize_attrs) + _pango_attr_list_get_iterator (itemize_attrs, &iter); + } + else + { + shape_attrs = NULL; + itemize_attrs = NULL; + } layout->log_attrs = g_new (PangoLogAttr, layout->n_chars + 1); -- cgit v1.2.1 From 9b7b67f5e01397de03bf46bb5f8446c30952fb33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 17 Apr 2020 20:23:09 +0200 Subject: layout: Unconditionally unref attr lists --- pango/pango-layout.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 07a32664..11e14418 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -4411,11 +4411,8 @@ pango_layout_check_lines (PangoLayout *layout) _pango_attr_iterator_destroy (&iter); } - if (shape_attrs) - pango_attr_list_unref (shape_attrs); - - if (attrs) - pango_attr_list_unref (attrs); + pango_attr_list_unref (shape_attrs); + pango_attr_list_unref (attrs); } #pragma GCC diagnostic pop -- cgit v1.2.1 From ea6248f5195bcfb1f11a20c7edb5fae6ab85e64d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 8 Jun 2020 19:20:14 +0200 Subject: layout: Treat empty attr lists like NULL ones --- pango/pango-attributes.c | 2 +- pango/pango-layout.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c index 84d24838..97c7aeaf 100644 --- a/pango/pango-attributes.c +++ b/pango/pango-attributes.c @@ -1992,7 +1992,7 @@ pango_attr_list_equal (PangoAttrList *list, gboolean _pango_attr_list_has_attributes (const PangoAttrList *list) { - return (list->attributes != NULL); + return list && (list->attributes != NULL); } G_DEFINE_BOXED_TYPE (PangoAttrIterator, diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 11e14418..7824a3ce 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -685,9 +685,15 @@ pango_layout_set_attributes (PangoLayout *layout, g_return_if_fail (layout != NULL); + /* Both empty */ if (!attrs && !layout->attrs) return; + /* Also both empty */ + if (!_pango_attr_list_has_attributes (layout->attrs) && + !_pango_attr_list_has_attributes (attrs)) + return; + old_attrs = layout->attrs; /* We always clear lines such that this function can be called -- cgit v1.2.1 From cc3d06b60c507ee1c75cd9c3677377cd30df0e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 17 Apr 2020 19:37:23 +0200 Subject: testattributes: Test iter on empty attr list --- tests/testattributes.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/testattributes.c b/tests/testattributes.c index eaca6663..6b5e849b 100644 --- a/tests/testattributes.c +++ b/tests/testattributes.c @@ -358,6 +358,15 @@ test_iter (void) PangoAttrIterator *copy; gint start, end; + /* Empty list */ + list = pango_attr_list_new (); + iter = pango_attr_list_get_iterator (list); + + g_assert_false (pango_attr_iterator_next (iter)); + g_assert_null (pango_attr_iterator_get_attrs (iter)); + pango_attr_iterator_destroy (iter); + pango_attr_list_unref (list); + list = pango_attr_list_new (); attr = pango_attr_size_new (10); pango_attr_list_insert (list, attr); -- cgit v1.2.1 From f5126639d6b4d699c1a55a66135192fdd551cc26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 17 Apr 2020 21:18:25 +0200 Subject: test-common: Ignore null attr lists pango_layout_get_attributes() is explicitly nullable but not every caller handles that case. --- tests/test-common.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test-common.c b/tests/test-common.c index 608b405c..786973f1 100644 --- a/tests/test-common.c +++ b/tests/test-common.c @@ -151,6 +151,9 @@ print_attr_list (PangoAttrList *attrs, GString *string) { PangoAttrIterator *iter; + if (!attrs) + return; + iter = pango_attr_list_get_iterator (attrs); do { gint start, end; -- cgit v1.2.1 From 4d8e71471984fb0fc147d1a64695ad5f18576fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 8 Jun 2020 19:36:48 +0200 Subject: tests: Update expected output We don't set an attribute list in these cases anymore, so reflect that in the output. --- tests/layouts/valid-3.expected | 1 - tests/layouts/valid-4.expected | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/layouts/valid-3.expected b/tests/layouts/valid-3.expected index 247c61bf..7f9d9e2f 100644 --- a/tests/layouts/valid-3.expected +++ b/tests/layouts/valid-3.expected @@ -8,7 +8,6 @@ lines: 2 --- attributes -range 0 2147483647 --- lines diff --git a/tests/layouts/valid-4.expected b/tests/layouts/valid-4.expected index 09f143f3..dae4e065 100644 --- a/tests/layouts/valid-4.expected +++ b/tests/layouts/valid-4.expected @@ -9,7 +9,6 @@ width: 194560 --- attributes -range 0 2147483647 --- lines -- cgit v1.2.1