From 2e6f2eb8148220b09d4834065d53c73a3ac2427b Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 4 Aug 2019 09:43:08 -0400 Subject: Add an insert-hyphens attribute Add a text attribute that allows to suppress insertion of hyphens at intra-word line breaks. This is useful for non-paragraph-like contexts, where line breaks are needed, but hyphens are not expected. --- docs/pango-sections.txt | 1 + pango/pango-attributes.c | 27 +++++++++++++++++++++++++++ pango/pango-attributes.h | 4 ++++ pango/pango-layout.c | 37 +++++++++++++++++++++++++++++++++++-- pango/pango-markup.c | 18 ++++++++++++++++++ tests/test-common.c | 1 + 6 files changed, 86 insertions(+), 2 deletions(-) diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt index 7a95d401..c179633b 100644 --- a/docs/pango-sections.txt +++ b/docs/pango-sections.txt @@ -413,6 +413,7 @@ pango_attr_font_features_new pango_attr_foreground_alpha_new pango_attr_background_alpha_new pango_attr_allow_breaks_new +pango_attr_insert_hyphens_new PangoShowFlags pango_attr_show_new PangoColor diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c index 2f02e264..9a80f0e1 100644 --- a/pango/pango-attributes.c +++ b/pango/pango-attributes.c @@ -1206,6 +1206,33 @@ pango_attr_allow_breaks_new (gboolean allow_breaks) return pango_attr_int_new (&klass, (int)allow_breaks); } +/** + * pango_attr_insert_hyphens_new: + * @insert_hyphens: %TRUE if hyphens should be inserted + * + * Create a new insert-hyphens attribute. + * + * Pango will insert hyphens when breaking lines in the middle + * of a word. This attribute can be used to suppress the hyphen. + * + * Return value: (transfer full): the newly allocated #PangoAttribute, + * which should be freed with pango_attribute_destroy() + * + * Since: 1.44 + */ +PangoAttribute * +pango_attr_insert_hyphens_new (gboolean insert_hyphens) +{ + static const PangoAttrClass klass = { + PANGO_ATTR_INSERT_HYPHENS, + pango_attr_int_copy, + pango_attr_int_destroy, + pango_attr_int_equal, + }; + + return pango_attr_int_new (&klass, (int)insert_hyphens); +} + /** * pango_attr_show_new: * @flags: #PangoShowFlags to apply diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h index b9ab6459..f60806f4 100644 --- a/pango/pango-attributes.h +++ b/pango/pango-attributes.h @@ -149,6 +149,7 @@ typedef struct _PangoAttrIterator PangoAttrIterator; * @PANGO_ATTR_BACKGROUND_ALPHA: background alpha (#PangoAttrInt). Since 1.38 * @PANGO_ATTR_ALLOW_BREAKS: whether breaks are allowed (#PangoAttrInt). Since 1.44 * @PANGO_ATTR_SHOW: how to render invisible characters (#PangoAttrInt). Since 1.44 + * @PANGO_ATTR_INSERT_HYPHENS: whether to insert hyphens at intra-word line breaks (#PangoAttrInt). Since 1.44 * * The #PangoAttrType * distinguishes between different types of attributes. Along with the @@ -187,6 +188,7 @@ typedef enum PANGO_ATTR_BACKGROUND_ALPHA, /* PangoAttrInt */ PANGO_ATTR_ALLOW_BREAKS, /* PangoAttrInt */ PANGO_ATTR_SHOW, /* PangoAttrInt */ + PANGO_ATTR_INSERT_HYPHENS, /* PangoAttrInt */ } PangoAttrType; /** @@ -528,6 +530,8 @@ PANGO_AVAILABLE_IN_1_38 PangoAttribute *pango_attr_background_alpha_new (guint16 alpha); PANGO_AVAILABLE_IN_1_44 PangoAttribute *pango_attr_allow_breaks_new (gboolean allow_breaks); +PANGO_AVAILABLE_IN_1_44 +PangoAttribute *pango_attr_insert_hyphens_new (gboolean insert_hyphens); /** * PangoShowFlags: diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 0ddb6e14..725ef0e0 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -3327,7 +3327,7 @@ struct _ParaBreakState int log_widths_offset; /* Offset into log_widths to the point corresponding * to the remaining portion of the first item */ - int *need_hyphen; /* is this char a soft hyphen ? */ + int *need_hyphen; /* Insert a hyphen if breaking here ? */ int line_start_index; /* Start index (byte offset) of line in layout->text */ int line_start_offset; /* Character offset of line in layout->text */ @@ -3432,12 +3432,41 @@ get_need_hyphen (PangoItem *item, const char *p; gboolean prev_space; gboolean prev_hyphen; + PangoAttrList *attrs; + PangoAttrIterator *iter; + GSList *l; + + attrs = pango_attr_list_new (); + 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)); + } + iter = pango_attr_list_get_iterator (attrs); for (i = 0, p = text + item->offset; i < item->num_chars; i++, p = g_utf8_next_char (p)) { gunichar wc = g_utf8_get_char (p); gboolean space; gboolean hyphen; + int start, end, pos; + gboolean insert_hyphens = TRUE; + + pos = p - text; + do { + pango_attr_iterator_range (iter, &start, &end); + if (end > pos) + break; + } while (pango_attr_iterator_next (iter)); + + if (start <= pos && pos < end) + { + PangoAttribute *attr; + attr = pango_attr_iterator_get (iter, PANGO_ATTR_INSERT_HYPHENS); + if (attr) + insert_hyphens = ((PangoAttrInt*)attr)->value; + } switch (g_unichar_type (wc)) { @@ -3479,11 +3508,14 @@ get_need_hyphen (PangoItem *item, else if (prev_hyphen || hyphen) need_hyphen[i] = FALSE; else - need_hyphen[i] = TRUE; + need_hyphen[i] = insert_hyphens; prev_space = space; prev_hyphen = hyphen; } + + pango_attr_iterator_destroy (iter); + pango_attr_list_unref (attrs); } static gboolean @@ -4074,6 +4106,7 @@ affects_break_or_shape (PangoAttribute *attr, /* Affects breaks */ case PANGO_ATTR_ALLOW_BREAKS: /* Affects shaping */ + case PANGO_ATTR_INSERT_HYPHENS: case PANGO_ATTR_FONT_FEATURES: case PANGO_ATTR_SHOW: return TRUE; diff --git a/pango/pango-markup.c b/pango/pango-markup.c index e39730e4..6dce1b2e 100644 --- a/pango/pango-markup.c +++ b/pango/pango-markup.c @@ -158,6 +158,10 @@ * not allowed, the range will be kept in a single run as far * as possible. Breaks are allowed by default. * + * insert_hyphens + * : 'true' or 'false' whether to insert hyphens when breaking + * lines in the middle of a word. Hyphens are inserted by default. + * * show * : A value determining how invisible characters are treated. * Possible values are 'spaces', 'line-breaks', 'ignorables' @@ -1334,6 +1338,7 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED, const char *alpha = NULL; const char *background_alpha = NULL; const char *allow_breaks = NULL; + const char *insert_hyphens = NULL; const char *show = NULL; g_markup_parse_context_get_position (context, @@ -1407,6 +1412,9 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED, CHECK_ATTRIBUTE (gravity); CHECK_ATTRIBUTE (gravity_hint); break; + case 'i': + CHECK_ATTRIBUTE (insert_hyphens); + break; case 'l': CHECK_ATTRIBUTE (lang); CHECK_ATTRIBUTE (letter_spacing); @@ -1767,6 +1775,16 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED, add_attribute (tag, pango_attr_allow_breaks_new (b)); } + if (G_UNLIKELY (insert_hyphens)) + { + gboolean b = FALSE; + + if (!span_parse_boolean ("insert_hyphens", insert_hyphens, &b, line_number, error)) + goto error; + + add_attribute (tag, pango_attr_insert_hyphens_new (b)); + } + return TRUE; error: diff --git a/tests/test-common.c b/tests/test-common.c index 3b1620ed..012059f4 100644 --- a/tests/test-common.c +++ b/tests/test-common.c @@ -119,6 +119,7 @@ print_attribute (PangoAttribute *attr, GString *string) case PANGO_ATTR_FOREGROUND_ALPHA: case PANGO_ATTR_BACKGROUND_ALPHA: case PANGO_ATTR_ALLOW_BREAKS: + case PANGO_ATTR_INSERT_HYPHENS: case PANGO_ATTR_SHOW: g_string_append_printf (string, "%d", ((PangoAttrInt *)attr)->value); break; -- cgit v1.2.1