diff options
author | Matthias Clasen <mclasen@redhat.com> | 2019-07-15 20:58:13 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2019-07-20 11:53:00 -0700 |
commit | 1074fcae667461fda72fc85551f37a6fe7eb40ac (patch) | |
tree | 67442ab8ace7395f02b92de4f8ae0a514d8d2841 | |
parent | 5c5c7bb310d886c1c4900440aefda78d676c691b (diff) | |
download | pango-1074fcae667461fda72fc85551f37a6fe7eb40ac.tar.gz |
Don't insert extra runs for hyphens
Instead, reshape the pre-break run with the
soft hyphen replaced by an actual hyphen.
This is unfortunately inefficient, we copy
the entire text for this. The alternative
(scatter-gather populating the harfbuzz
buffer) is too hard to manage.
-rw-r--r-- | docs/pango-sections.txt | 1 | ||||
-rw-r--r-- | pango/pango-item.h | 12 | ||||
-rw-r--r-- | pango/pango-layout.c | 133 | ||||
-rw-r--r-- | pango/pangofc-shape.c | 14 |
4 files changed, 56 insertions, 104 deletions
diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt index 9d08d0b2..f89debe6 100644 --- a/docs/pango-sections.txt +++ b/docs/pango-sections.txt @@ -6,6 +6,7 @@ PangoItem PangoAnalysis PANGO_ANALYSIS_FLAG_CENTERED_BASELINE PANGO_ANALYSIS_FLAG_IS_ELLIPSIS +PANGO_ANALYSIS_FLAG_NEED_HYPHEN PANGO_TYPE_DIRECTION <SUBSECTION> diff --git a/pango/pango-item.h b/pango/pango-item.h index 2a7bcb2a..d4162f90 100644 --- a/pango/pango-item.h +++ b/pango/pango-item.h @@ -51,13 +51,23 @@ typedef struct _PangoItem PangoItem; #define PANGO_ANALYSIS_FLAG_IS_ELLIPSIS (1 << 1) /** + * PANGO_ANALYSIS_FLAG_NEED_HYPHEN: + * + * This flag tells Pango to add a hyphen at the end of the + * run during shaping. + * + * Since: 1.44 + */ +#define PANGO_ANALYSIS_FLAG_NEED_HYPHEN (1 << 2) + +/** * PangoAnalysis: * @shape_engine: unused * @lang_engine: unused * @font: the font for this segment. * @level: the bidirectional level for this segment. * @gravity: the glyph orientation for this segment (A #PangoGravity). - * @flags: boolean flags for this segment (currently only one) (Since: 1.16). + * @flags: boolean flags for this segment (Since: 1.16). * @script: the detected script for this segment (A #PangoScript) (Since: 1.18). * @language: the detected language for this segment. * @extra_attrs: extra attributes for this segment. diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 7735d6f2..2387e1cd 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -3337,9 +3337,9 @@ shape_run (PangoLayoutLine *line, state->properties.shape_ink_rect, state->properties.shape_logical_rect, glyphs); else - pango_shape_full (layout->text + item->offset, item->length, - layout->text, layout->length, - &item->analysis, glyphs); + pango_shape_full (layout->text + item->offset, item->length, + layout->text, layout->length, + &item->analysis, glyphs); if (state->properties.letter_spacing) { @@ -3396,73 +3396,6 @@ insert_run (PangoLayoutLine *line, } static void -advance_iterator_to (PangoAttrIterator *iter, - int new_index) -{ - int start, end; - - do - { - pango_attr_iterator_range (iter, &start, &end); - if (end > new_index) - break; - } - while (pango_attr_iterator_next (iter)); -} - -static PangoLayoutRun * -create_hyphen_run (PangoLayout *layout, - PangoItem *item) -{ - PangoLayoutRun *run; - GList *items; - const char *hyphen_text = "-"; - int hyphen_len = 1; - PangoAttrList *attrs; - PangoAttrIterator *iter; - GSList *list, *l; - PangoAttrList *run_attrs; - - run_attrs = pango_attr_list_new (); - - attrs = pango_layout_get_effective_attributes (layout); - iter = pango_attr_list_get_iterator (attrs); - - advance_iterator_to (iter, item->offset + item->length); - list = pango_attr_iterator_get_attrs (iter); - for (l = list; l; l = l->next) - { - PangoAttribute *attr = l->data; - attr->start_index = 0; - attr->end_index = G_MAXINT; - pango_attr_list_insert (attrs, attr); - } - g_slist_free (list); - - items = pango_itemize (layout->context, hyphen_text, 0, hyphen_len, attrs, NULL); - g_assert (items->next == NULL); - - run = g_slice_new (PangoGlyphItem); - run->glyphs = pango_glyph_string_new (); - run->item = items->data; - - /* insert after item, use SHY as text */ - run->item->offset = item->offset + item->length; - run->item->length = 2; - run->item->num_chars = 1; - - g_list_free (items); - - pango_shape (hyphen_text, hyphen_len, &run->item->analysis, run->glyphs); - - pango_attr_iterator_destroy (iter); - pango_attr_list_unref (attrs); - pango_attr_list_unref (run_attrs); - - return run; -} - -static void get_need_hyphen (PangoItem *item, const char *text, int *need_hyphen) @@ -3492,22 +3425,36 @@ break_needs_hyphen (PangoLayout *layout, } static int +find_hyphen_width (PangoItem *item) +{ + hb_font_t *hb_font; + hb_codepoint_t glyph; + + /* This is not technically correct, since we + * a) we may end up inserting a different hyphen + * b) we should reshape the entire run + * But it is close enough in practice + */ + hb_font = pango_font_get_hb_font (item->analysis.font); + if (hb_font_get_nominal_glyph (hb_font, 0x2010, &glyph) || + hb_font_get_nominal_glyph (hb_font, '-', &glyph)) + return hb_font_get_glyph_h_advance (hb_font, glyph); + + return 0; +} + +static int find_break_extra_width (PangoLayout *layout, ParaBreakState *state, int pos) { - PangoItem *item = state->items->data; - /* Check whether to insert a hyphen */ if (break_needs_hyphen (layout, state, pos)) { if (state->hyphen_width < 0) { - PangoLayoutRun *run; - - run = create_hyphen_run (layout, item); - state->hyphen_width = pango_glyph_string_get_width (run->glyphs); - pango_glyph_item_free (run); + PangoItem *item = state->items->data; + state->hyphen_width = find_hyphen_width (item); } return state->hyphen_width; @@ -3516,23 +3463,6 @@ find_break_extra_width (PangoLayout *layout, return 0; } -static void -insert_hyphen_after (PangoLayoutLine *line, - ParaBreakState *state, - PangoItem *item) -{ - PangoLayout *layout = line->layout; - PangoLayoutRun *run; - - /* Use the SHY as text for the hyphen run */ - item->num_chars -= 1; - item->length -= 2; - run = create_hyphen_run (layout, item); - line->runs = g_slist_prepend (line->runs, run); - - state->remaining_width -= pango_glyph_string_get_width (run->glyphs); -} - #if 0 # define DEBUG debug void @@ -3713,10 +3643,9 @@ process_item (PangoLayout *layout, if (break_num_chars == item->num_chars) { - gboolean insert_hyphen = break_needs_hyphen (layout, state, break_num_chars); + if (break_needs_hyphen (layout, state, break_num_chars)) + item->analysis.flags |= PANGO_ANALYSIS_FLAG_NEED_HYPHEN; insert_run (line, state, item, TRUE); - if (insert_hyphen) - insert_hyphen_after (line, state, item); return BREAK_ALL_FIT; } @@ -3727,26 +3656,24 @@ process_item (PangoLayout *layout, else { PangoItem *new_item; - gboolean insert_hyphen = break_needs_hyphen (layout, state, break_num_chars); length = g_utf8_offset_to_pointer (layout->text + item->offset, break_num_chars) - (layout->text + item->offset); new_item = pango_item_split (item, length, break_num_chars); + if (break_needs_hyphen (layout, state, break_num_chars)) + new_item->analysis.flags |= PANGO_ANALYSIS_FLAG_NEED_HYPHEN; /* Add the width back, to the line, reshape, subtract the new width */ state->remaining_width += break_width; insert_run (line, state, new_item, FALSE); break_width = pango_glyph_string_get_width (((PangoGlyphItem *)(line->runs->data))->glyphs); state->remaining_width -= break_width; + state->log_widths_offset += break_num_chars; + /* Shaped items should never be broken */ g_assert (!shape_set); - if (insert_hyphen) - insert_hyphen_after (line, state, new_item); - - state->log_widths_offset += break_num_chars; - return BREAK_SOME_FIT; } } diff --git a/pango/pangofc-shape.c b/pango/pangofc-shape.c index 910ff4d7..12ce7ddb 100644 --- a/pango/pangofc-shape.c +++ b/pango/pangofc-shape.c @@ -158,6 +158,20 @@ pango_hb_shape (PangoFont *font, hb_buffer_set_flags (hb_buffer, HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT); hb_buffer_add_utf8 (hb_buffer, paragraph_text, paragraph_length, item_offset, item_length); + if (analysis->flags & PANGO_ANALYSIS_FLAG_NEED_HYPHEN) + { + /* Insert either a Unicode or ASCII hyphen. We may + * want to look for script-specific hyphens here. + */ + const char *p = paragraph_text + item_offset + item_length; + int last_char_len = p - g_utf8_prev_char (p); + hb_codepoint_t glyph; + + if (hb_font_get_nominal_glyph (hb_font, 0x2010, &glyph)) + hb_buffer_add (hb_buffer, 0x2010, item_length - last_char_len); + else if (hb_font_get_nominal_glyph (hb_font, '-', &glyph)) + hb_buffer_add (hb_buffer, '-', item_length - last_char_len); + } pango_font_get_features (font, features, G_N_ELEMENTS (features), &num_features); apply_extra_attributes (analysis->extra_attrs, features, G_N_ELEMENTS (features), &num_features); |