summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2019-07-15 20:58:13 -0400
committerMatthias Clasen <mclasen@redhat.com>2019-07-20 11:53:00 -0700
commit1074fcae667461fda72fc85551f37a6fe7eb40ac (patch)
tree67442ab8ace7395f02b92de4f8ae0a514d8d2841
parent5c5c7bb310d886c1c4900440aefda78d676c691b (diff)
downloadpango-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.txt1
-rw-r--r--pango/pango-item.h12
-rw-r--r--pango/pango-layout.c133
-rw-r--r--pango/pangofc-shape.c14
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);