From 4315d4f49b054e8d322fe87845bc3843f7523835 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 11 Jul 2019 11:31:43 -0400 Subject: Add pango_item_apply_attrs This adds attrs that are overlapping the range of the item to the extra_attrs in the analysis. --- pango/pango-item.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ pango/pango-item.h | 4 ++++ 2 files changed, 49 insertions(+) diff --git a/pango/pango-item.c b/pango/pango-item.c index 8c368874..787fb65e 100644 --- a/pango/pango-item.c +++ b/pango/pango-item.c @@ -153,3 +153,48 @@ pango_item_split (PangoItem *orig, return new_item; } + +static int +compare_attr (gconstpointer p1, gconstpointer p2) +{ + if (pango_attribute_equal ((PangoAttribute *)p1, (PangoAttribute *)p2)) + return 0; + + return 1; +} + +void +pango_item_apply_attrs (PangoItem *item, + PangoAttrIterator *iter) +{ + int start, end; + GSList *attrs = NULL; + + do + { + pango_attr_iterator_range (iter, &start, &end); + + if (start >= item->offset + item->length) + break; + + if (end >= item->offset) + { + GSList *list, *l; + + list = pango_attr_iterator_get_attrs (iter); + for (l = list; l; l = l->next) + { + if (!g_slist_find_custom (attrs, l->data, compare_attr)) + + attrs = g_slist_prepend (attrs, pango_attribute_copy (l->data)); + } + g_slist_free_full (list, (GDestroyNotify)pango_attribute_destroy); + } + + if (end >= item->offset + item->length) + break; + } + while (pango_attr_iterator_next (iter)); + + item->analysis.extra_attrs = g_slist_concat (item->analysis.extra_attrs, attrs); +} diff --git a/pango/pango-item.h b/pango/pango-item.h index cb6a7ed3..2d7e58a1 100644 --- a/pango/pango-item.h +++ b/pango/pango-item.h @@ -23,6 +23,7 @@ #define __PANGO_ITEM_H__ #include +#include G_BEGIN_DECLS @@ -112,6 +113,9 @@ PANGO_AVAILABLE_IN_ALL PangoItem *pango_item_split (PangoItem *orig, int split_index, int split_offset); +PANGO_AVAILABLE_IN_1_44 +void pango_item_apply_attrs (PangoItem *item, + PangoAttrIterator *iter); G_END_DECLS -- cgit v1.2.1 From a0483fc2157a7efbf153effec0b241583e43e047 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 11 Jul 2019 11:32:22 -0400 Subject: layout: Don't break runs for font_features Don't pass font_features attributes into the itemize run, since we don't need to break runs for this. Split them off, and reapply them after itemization. We rapply them before line breaking, since we want them to affect the shaping. Closes: https://gitlab.gnome.org/GNOME/pango/issues/242 --- pango/pango-layout.c | 84 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 19 deletions(-) diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 2384d6b0..97beccc8 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -4006,11 +4006,6 @@ no_shape_filter_func (PangoAttribute *attribute, PANGO_ATTR_UNDERLINE, PANGO_ATTR_STRIKETHROUGH, PANGO_ATTR_RISE - /* Ideally we want font-features here, because we don't - * want it to break shaping runs. But if we put it here, - * it won't show up in the shaper anymore :(. To be - * fixed later. */ - /* PANGO_ATTR_FONT_FEATURES */ }; int i; @@ -4032,33 +4027,76 @@ filter_no_shape_attributes (PangoAttrList *attrs) static void apply_no_shape_attributes (PangoLayout *layout, - PangoAttrList *no_shape_attrs) + PangoAttrList *no_shape_attrs) { - GSList *line_list; + GSList *ll; - for (line_list = layout->lines; line_list; line_list = line_list->next) + for (ll = layout->lines; ll; ll = ll->next) { - PangoLayoutLine *line = line_list->data; + PangoLayoutLine *line = ll->data; GSList *old_runs = g_slist_reverse (line->runs); - GSList *run_list; + GSList *rl; line->runs = NULL; - for (run_list = old_runs; run_list; run_list = run_list->next) - { - PangoGlyphItem *glyph_item = run_list->data; - GSList *new_runs; + for (rl = old_runs; rl; rl = rl->next) + { + PangoGlyphItem *glyph_item = rl->data; + GSList *new_runs; - new_runs = pango_glyph_item_apply_attrs (glyph_item, - layout->text, - no_shape_attrs); + new_runs = pango_glyph_item_apply_attrs (glyph_item, + layout->text, + no_shape_attrs); - line->runs = g_slist_concat (new_runs, line->runs); - } + line->runs = g_slist_concat (new_runs, line->runs); + } g_slist_free (old_runs); } } +static gboolean +no_break_filter_func (PangoAttribute *attribute, + gpointer data G_GNUC_UNUSED) +{ + static const PangoAttrType no_break_types[] = { + PANGO_ATTR_FONT_FEATURES + }; + + int i; + + for (i = 0; i < (int)G_N_ELEMENTS (no_break_types); i++) + if (attribute->klass->type == no_break_types[i]) + return TRUE; + + return FALSE; +} + +static PangoAttrList * +filter_no_break_attributes (PangoAttrList *attrs) +{ + return pango_attr_list_filter (attrs, + no_break_filter_func, + NULL); +} + +static void +apply_no_break_attributes (GList *items, + PangoAttrList *no_break_attrs) +{ + GList *l; + PangoAttrIterator *iter; + + iter = pango_attr_list_get_iterator (no_break_attrs); + + for (l = items; l; l = l->next) + { + PangoItem *item = l->data; + pango_item_apply_attrs (item, iter); + } + + pango_attr_iterator_destroy (iter); +} + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -4070,6 +4108,7 @@ pango_layout_check_lines (PangoLayout *layout) int start_offset; PangoAttrList *attrs; PangoAttrList *no_shape_attrs; + PangoAttrList *no_break_attrs; PangoAttrIterator *iter; PangoDirection prev_base_dir = PANGO_DIRECTION_NEUTRAL, base_dir = PANGO_DIRECTION_NEUTRAL; ParaBreakState state; @@ -4089,6 +4128,7 @@ pango_layout_check_lines (PangoLayout *layout) attrs = pango_layout_get_effective_attributes (layout); no_shape_attrs = filter_no_shape_attributes (attrs); + no_break_attrs = filter_no_break_attributes (attrs); iter = pango_attr_list_get_iterator (attrs); layout->log_attrs = g_new (PangoLogAttr, layout->n_chars + 1); @@ -4169,6 +4209,12 @@ pango_layout_check_lines (PangoLayout *layout) attrs, iter); + if (no_break_attrs) + { + apply_no_break_attributes (state.items, no_break_attrs); + pango_attr_list_unref (no_break_attrs); + } + get_items_log_attrs (start, state.items, layout->log_attrs + start_offset, delim_len); -- cgit v1.2.1 From 3af161ea86f4f543ba7a6bb16f83595b980e5d04 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 11 Jul 2019 11:51:25 -0400 Subject: Add a test for itemization with attributes This tests that font_fatures don't break runs anymore. --- tests/itemize/two.expected | 8 ++++++++ tests/itemize/two.items | 3 +++ 2 files changed, 11 insertions(+) create mode 100644 tests/itemize/two.expected create mode 100644 tests/itemize/two.items diff --git a/tests/itemize/two.expected b/tests/itemize/two.expected new file mode 100644 index 00000000..f0adbad0 --- /dev/null +++ b/tests/itemize/two.expected @@ -0,0 +1,8 @@ +one two two three + +Items: one |tw |o | |two | |th |r |ee +Font: Cantarell 11|Cantarell 11 |Cantarell 11 |Cantarell 11 |Cantarell 11 |Cantarell 11 |Cantarell 11|Cantarell Bold 11|Cantarell 11 +Script: Latn |Latn |Latn |Latn |Latn |Latn |Latn |Latn |Latn +Lang: en-us |en-us |en-us |en-us |en-us |en-us |en-us |en-us |en-us +Bidi: 0 |0 |0 |0 |0 |0 |0 |0 |0 +Attrs: |[4,12]features=tnum=0|[4,12]features=tnum=0,[6,7]underline=1|[4,12]features=tnum=0|[4,12]features=tnum=0,[8,11]features=dlig=1|[4,12]features=tnum=0| | | diff --git a/tests/itemize/two.items b/tests/itemize/two.items new file mode 100644 index 00000000..4ba41454 --- /dev/null +++ b/tests/itemize/two.items @@ -0,0 +1,3 @@ +# test that font_features attributes don't break the +# runs anymore (but other attributes do) +one two two three -- cgit v1.2.1 From 9307a8c38a55056147b931c429d60409cb4bd779 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 11 Jul 2019 15:06:51 -0400 Subject: Set ranges on features Before passing the features to hb_shape(), set their ranges, since they are no longer always for the full length of the item. --- pango/pangofc-shape.c | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/pango/pangofc-shape.c b/pango/pangofc-shape.c index b062bd26..2846449e 100644 --- a/pango/pangofc-shape.c +++ b/pango/pangofc-shape.c @@ -440,10 +440,11 @@ _pango_fc_shape (PangoFont *font, GSList *tmp_attrs; for (tmp_attrs = analysis->extra_attrs; tmp_attrs && num_features < G_N_ELEMENTS (features); tmp_attrs = tmp_attrs->next) - { - if (((PangoAttribute *) tmp_attrs->data)->klass->type == PANGO_ATTR_FONT_FEATURES) - { - const PangoAttrFontFeatures *fattr = (const PangoAttrFontFeatures *) tmp_attrs->data; + { + PangoAttribute *attr = tmp_attrs->data; + if (attr->klass->type == PANGO_ATTR_FONT_FEATURES) + { + PangoAttrFontFeatures *fattr = (PangoAttrFontFeatures *) attr; const gchar *feat; const gchar *end; int len; @@ -451,23 +452,26 @@ _pango_fc_shape (PangoFont *font, feat = fattr->features; while (feat != NULL && num_features < G_N_ELEMENTS (features)) - { - end = strchr (feat, ','); - if (end) - len = end - feat; - else - len = -1; - - if (hb_feature_from_string (feat, len, &features[num_features])) - num_features++; - - if (end == NULL) - break; - - feat = end + 1; - } - } - } + { + end = strchr (feat, ','); + if (end) + len = end - feat; + else + len = -1; + if (hb_feature_from_string (feat, len, &features[num_features])) + { + features[num_features].start = attr->start_index; + features[num_features].end = attr->end_index; + num_features++; + } + + if (end == NULL) + break; + + feat = end + 1; + } + } + } } hb_shape (hb_font, hb_buffer, features, num_features); -- cgit v1.2.1