summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml1
-rw-r--r--docs/pango-sections.txt2
-rw-r--r--pango/break.c98
-rw-r--r--pango/pango-attributes.c27
-rw-r--r--pango/pango-attributes.h6
-rw-r--r--pango/pango-break.h5
-rw-r--r--pango/pango-item.h12
-rw-r--r--pango/pango-layout.c207
-rw-r--r--pango/pango-markup.c17
-rw-r--r--pango/pangofc-font.c4
-rw-r--r--pango/pangofc-shape.c14
-rw-r--r--tests/breaks/one.expected10
-rw-r--r--tests/breaks/three.expected10
-rw-r--r--tests/breaks/two.expected10
-rw-r--r--tests/layouts/valid-4.expected24
-rw-r--r--tests/test-break.c22
-rw-r--r--tests/testiter.c11
-rw-r--r--utils/test-hyphens.txt4
18 files changed, 297 insertions, 187 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a33020b5..a832e53e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -20,6 +20,7 @@ gnome-runtime-linux:
gobject-introspection-devel \
cairo-gobject-devel \
abattis-cantarell-fonts \
+ google-droid-sans-fonts \
desktop-file-utils
script:
- meson _build
diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt
index 11aabcae..5050a1f3 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>
@@ -407,6 +408,7 @@ pango_attr_gravity_hint_new
pango_attr_font_features_new
pango_attr_foreground_alpha_new
pango_attr_background_alpha_new
+pango_attr_allow_breaks_new_
PangoColor
PANGO_TYPE_COLOR
pango_color_parse
diff --git a/pango/break.c b/pango/break.c
index 8ed8e8c1..356c5afe 100644
--- a/pango/break.c
+++ b/pango/break.c
@@ -1578,18 +1578,34 @@ break_script (const char *item_text,
int attrs_len);
static gboolean
-tailor_break (const gchar *text,
- gint length,
- PangoAnalysis *analysis,
- PangoLogAttr *attrs,
- int attrs_len)
+break_attrs (const char *text,
+ int length,
+ GSList *attributes,
+ int item_offset,
+ PangoLogAttr *attrs,
+ int attrs_len);
+
+static gboolean
+tailor_break (const char *text,
+ int length,
+ PangoAnalysis *analysis,
+ int item_offset,
+ PangoLogAttr *attrs,
+ int attrs_len)
{
+ gboolean res;
+
if (length < 0)
length = strlen (text);
else if (text == NULL)
text = "";
- return break_script (text, length, analysis, attrs, attrs_len);
+ res = break_script (text, length, analysis, attrs, attrs_len);
+
+ if (item_offset >= 0)
+ res |= break_attrs (text, length, analysis->extra_attrs, item_offset, attrs, attrs_len);
+
+ return res;
}
/**
@@ -1618,7 +1634,7 @@ pango_break (const gchar *text,
g_return_if_fail (attrs != NULL);
pango_default_break (text, length, analysis, attrs, attrs_len);
- tailor_break (text, length, analysis, attrs, attrs_len);
+ tailor_break (text, length, analysis, -1, attrs, attrs_len);
}
/**
@@ -1726,6 +1742,8 @@ pango_find_paragraph_boundary (const gchar *text,
* @text: text to process. Must be valid UTF-8
* @length: length in bytes of @text
* @analysis: #PangoAnalysis structure from pango_itemize() for @text
+ * @offset: Byte offset of @text from the beginning of the
+ * paragraph, or -1 to ignore attributes from @analysis
* @log_attrs: (array length=attrs_len): array with one #PangoLogAttr
* per character in @text, plus one extra, to be filled in
* @attrs_len: length of @log_attrs array
@@ -1733,18 +1751,24 @@ pango_find_paragraph_boundary (const gchar *text,
* Apply language-specific tailoring to the breaks in
* @log_attrs, which are assumed to have been produced
* by pango_default_break().
+ *
+ * If @offset is not -1, it is used to apply attributes
+ * from @analysis that are relevant to line breaking.
+ *
+ * Since: 1.44
*/
void
pango_tailor_break (const char *text,
int length,
PangoAnalysis *analysis,
+ int offset,
PangoLogAttr *log_attrs,
int log_attrs_len)
{
PangoLogAttr *start = log_attrs;
PangoLogAttr attr_before = *start;
- if (tailor_break (text, length, analysis, log_attrs, log_attrs_len))
+ if (tailor_break (text, length, analysis, offset, log_attrs, log_attrs_len))
{
/* if tailored, we enforce some of the attrs from before
* tailoring at the boundary
@@ -1773,6 +1797,7 @@ tailor_segment (const char *range_start,
pango_tailor_break (range_start,
range_end - range_start,
analysis,
+ -1,
start,
chars_in_range + 1);
@@ -1877,3 +1902,60 @@ break_script (const char *item_text,
return TRUE;
}
+
+static gboolean
+break_attrs (const char *text,
+ int length,
+ GSList *attributes,
+ int offset,
+ PangoLogAttr *log_attrs,
+ int log_attrs_len)
+{
+ PangoAttrList *list;
+ PangoAttrIterator *iter;
+ GSList *l;
+
+ list = pango_attr_list_new ();
+ for (l = attributes; l; l = l->next)
+ {
+ PangoAttribute *attr = l->data;
+
+ if (attr->klass->type == PANGO_ATTR_ALLOW_BREAKS)
+ pango_attr_list_insert (list, (PangoAttribute*)l->data);
+ }
+
+ iter = pango_attr_list_get_iterator (list);
+ do {
+ PangoAttribute *attr;
+
+ 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);
+ if (start < offset)
+ start_pos = 0;
+ else
+ start_pos = g_utf8_pointer_to_offset (text, text + start - offset);
+ if (end >= offset + length)
+ end_pos = log_attrs_len;
+ else
+ end_pos = g_utf8_pointer_to_offset (text, text + end - offset);
+
+ for (pos = start_pos + 1; pos < end_pos; pos++)
+ {
+ log_attrs[pos].is_mandatory_break = FALSE;
+ log_attrs[pos].is_line_break = FALSE;
+ log_attrs[pos].is_char_break = FALSE;
+ }
+ }
+ } while (pango_attr_iterator_next (iter));
+
+ pango_attr_iterator_destroy (iter);
+ pango_attr_list_unref (list);
+
+ return TRUE;
+}
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 894555d1..15edfbe8 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -1179,6 +1179,33 @@ pango_attr_background_alpha_new (guint16 alpha)
return pango_attr_int_new (&klass, (int)alpha);
}
+/**
+ * pango_attr_allow_breaks_new:
+ * @allow_breaks: %TRUE if we line breaks are allowed
+ *
+ * Create a new allow-breaks attribute.
+ *
+ * If breaks are disabled, the range will be kept in a
+ * single run, as far as possible.
+ *
+ * Return value: (transfer full): the newly allocated #PangoAttribute,
+ * which should be freed with pango_attribute_destroy()
+ *
+ * Since: 1.44
+ */
+PangoAttribute *
+pango_attr_allow_breaks_new (gboolean allow_breaks)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_ALLOW_BREAKS,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal,
+ };
+
+ return pango_attr_int_new (&klass, (int)allow_breaks);
+}
+
/*
* Attribute List
*/
diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h
index 6f021c06..f7a0c1cb 100644
--- a/pango/pango-attributes.h
+++ b/pango/pango-attributes.h
@@ -147,6 +147,7 @@ typedef struct _PangoAttrIterator PangoAttrIterator;
* @PANGO_ATTR_FONT_FEATURES: OpenType font features (#PangoAttrString). Since 1.38
* @PANGO_ATTR_FOREGROUND_ALPHA: foreground alpha (#PangoAttrInt). Since 1.38
* @PANGO_ATTR_BACKGROUND_ALPHA: background alpha (#PangoAttrInt). Since 1.38
+ * @PANGO_ATTR_ALLOW_BREAKS: whether breaks are allowed (#PangoAttrInt). Since 1.44
*
* The #PangoAttrType
* distinguishes between different types of attributes. Along with the
@@ -182,7 +183,8 @@ typedef enum
PANGO_ATTR_GRAVITY_HINT, /* PangoAttrInt */
PANGO_ATTR_FONT_FEATURES, /* PangoAttrString */
PANGO_ATTR_FOREGROUND_ALPHA, /* PangoAttrInt */
- PANGO_ATTR_BACKGROUND_ALPHA /* PangoAttrInt */
+ PANGO_ATTR_BACKGROUND_ALPHA, /* PangoAttrInt */
+ PANGO_ATTR_ALLOW_BREAKS /* PangoAttrInt */
} PangoAttrType;
/**
@@ -522,6 +524,8 @@ PANGO_AVAILABLE_IN_1_38
PangoAttribute *pango_attr_foreground_alpha_new (guint16 alpha);
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_ALL
GType pango_attr_list_get_type (void) G_GNUC_CONST;
diff --git a/pango/pango-break.h b/pango/pango-break.h
index 4e1db0bc..19698db1 100644
--- a/pango/pango-break.h
+++ b/pango/pango-break.h
@@ -134,9 +134,10 @@ void pango_default_break (const gchar *text,
int attrs_len);
PANGO_AVAILABLE_IN_1_44
-void pango_tailor_break (const gchar *text,
- int length,
+void pango_tailor_break (const char *text,
+ int length,
PangoAnalysis *analysis,
+ int offset,
PangoLogAttr *attrs,
int attrs_len);
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..414525d7 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)
@@ -3472,8 +3405,37 @@ get_need_hyphen (PangoItem *item,
for (i = 0, p = text + item->offset; i < item->num_chars; i++, p = g_utf8_next_char (p))
{
- gunichar ch = g_utf8_get_char (p);
- need_hyphen[i] = ch == 0xad;
+ gunichar wc = g_utf8_get_char (p);
+ switch (g_unichar_type(wc))
+ {
+ case G_UNICODE_SPACE_SEPARATOR:
+ case G_UNICODE_LINE_SEPARATOR:
+ case G_UNICODE_PARAGRAPH_SEPARATOR:
+ need_hyphen[i] = FALSE;
+ break;
+ case G_UNICODE_CONTROL:
+ if (wc == '\t' || wc == '\n' || wc == '\r' || wc == '\f')
+ need_hyphen[i] = FALSE;
+ else
+ need_hyphen[i] = TRUE;
+ break;
+ default:
+ if (wc == '-' || /* Hyphen-minus */
+ wc == 0x058a || /* Armenian hyphen */
+ wc == 0x1400 || /* Canadian syllabics hyphen */
+ wc == 0x1806 || /* Mongolian todo hyphen */
+ wc == 0x2010 || /* Hyphen */
+ wc == 0x2027 || /* Hyphenation point */
+ wc == 0x2e17 || /* Double oblique hyphen */
+ wc == 0x2e40 || /* Double hyphen */
+ wc == 0x30a0 || /* Katakana-Hiragana double hyphen */
+ wc == 0xfe63 || /* Small hyphen-minus */
+ wc == 0xff0d) /* Fullwidth hyphen-minus */
+ need_hyphen[i] = FALSE;
+ else
+ need_hyphen[i] = TRUE;
+ break;
+ }
}
}
@@ -3492,22 +3454,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
+ * 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 +3492,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 +3672,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 +3685,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;
}
}
@@ -3994,44 +3950,23 @@ get_items_log_attrs (const char *text,
int log_attrs_len)
{
int offset = 0;
- int index = 0;
- int num_bytes = 0;
int num_chars = 0;
- PangoAnalysis analysis = { NULL };
GList *l;
- analysis.level = -1;
-
- pango_default_break (text, length, &analysis, log_attrs, log_attrs_len);
+ pango_default_break (text, length, NULL, log_attrs, log_attrs_len);
for (l = items; l; l = l->next)
{
PangoItem *item = l->data;
- if (l == items)
- {
- analysis = item->analysis;
- index = item->offset;
- offset = 0;
- }
+ pango_tailor_break (text + item->offset,
+ item->length,
+ &item->analysis,
+ item->offset,
+ log_attrs + offset,
+ item->num_chars + 1);
- if (can_break_together (&analysis, &item->analysis))
- {
- num_bytes += item->length;
- num_chars += item->num_chars;
- }
- else
- {
- pango_tailor_break (text + index,
- num_bytes,
- &analysis,
- log_attrs + offset,
- num_chars + 1);
-
- analysis = item->analysis;
- index += num_bytes;
- offset += num_chars;
- }
+ offset += num_chars;
}
}
@@ -4119,9 +4054,9 @@ no_break_filter_func (PangoAttribute *attribute,
gpointer data G_GNUC_UNUSED)
{
static const PangoAttrType no_break_types[] = {
- PANGO_ATTR_FONT_FEATURES
+ PANGO_ATTR_FONT_FEATURES,
+ PANGO_ATTR_ALLOW_BREAKS
};
-
int i;
for (i = 0; i < (int)G_N_ELEMENTS (no_break_types); i++)
diff --git a/pango/pango-markup.c b/pango/pango-markup.c
index 2c509dac..2b871584 100644
--- a/pango/pango-markup.c
+++ b/pango/pango-markup.c
@@ -153,6 +153,11 @@
* Fallback is enabled by default. Most applications should not
* disable fallback.
*
+ * allow_breaks
+ * : 'true' or 'false' whether to allow line breaks or not. If
+ * not allowed, the range will be kept in a single run as far
+ * as possible. Breaks are allowed by default.
+ *
* lang
* : A language code, indicating the text language
*
@@ -1297,6 +1302,7 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED,
const char *font_features = NULL;
const char *alpha = NULL;
const char *background_alpha = NULL;
+ const char *allow_breaks = NULL;
g_markup_parse_context_get_position (context,
&line_number, &char_number);
@@ -1326,6 +1332,7 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED,
switch (names[i][0]) {
case 'a':
+ CHECK_ATTRIBUTE (allow_breaks);
CHECK_ATTRIBUTE (alpha);
break;
case 'b':
@@ -1707,6 +1714,16 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED,
add_attribute (tag, pango_attr_font_features_new (font_features));
}
+ if (G_UNLIKELY (allow_breaks))
+ {
+ gboolean b = FALSE;
+
+ if (!span_parse_boolean ("allow_breaks", allow_breaks, &b, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_allow_breaks_new (b));
+ }
+
return TRUE;
error:
diff --git a/pango/pangofc-font.c b/pango/pangofc-font.c
index 17119436..0bb25ba5 100644
--- a/pango/pangofc-font.c
+++ b/pango/pangofc-font.c
@@ -861,7 +861,7 @@ extern gpointer get_gravity_class (void);
static PangoGravity
pango_fc_font_key_get_gravity (PangoFcFontKey *key)
{
- FcPattern *pattern;
+ const FcPattern *pattern;
PangoGravity gravity = PANGO_GRAVITY_SOUTH;
FcChar8 *s;
@@ -878,7 +878,7 @@ pango_fc_font_key_get_gravity (PangoFcFontKey *key)
static double
get_font_size (PangoFcFontKey *key)
{
- FcPattern *pattern;
+ const FcPattern *pattern;
double size;
double dpi;
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);
diff --git a/tests/breaks/one.expected b/tests/breaks/one.expected
index d474c6e4..66c6bd48 100644
--- a/tests/breaks/one.expected
+++ b/tests/breaks/one.expected
@@ -1,5 +1,5 @@
-Text: a b c / d e f [ ] g h i [0xad] j k l . [ ] B l a [0x0a]
-Breaks: c c c c lc c c c lc c c c lc c c c c lc c c c Lc
-Whitespace: x x w w
-Words: bs be bs be bs be b bs be b
-Sentences: bs e bs e b
+Text: a b c / d e f [ ] g h i [0xad] j k l . [ ] B l a [0x0a]
+Breaks: c c c c lc c c c lc c c c lc c c c c lc c c c c
+Whitespace: x x w w
+Words: bs be bs be bs be b bs be b
+Sentences: bs e bs e b
diff --git a/tests/breaks/three.expected b/tests/breaks/three.expected
index b7d8bd90..0e60f876 100644
--- a/tests/breaks/three.expected
+++ b/tests/breaks/three.expected
@@ -1,5 +1,5 @@
-Text: o n e [ ] t w o [0x2028] r e d [ ] b l u e[0x200d] g r e e n [0x0a]
-Breaks: c c c c lc c c c Lc c c c lc c c c c c c c c c Lc
-Whitespace: x w x w w
-Words: bs be bs be bs be bs be b
-Sentences: bs e bs e b
+Text: o n e [ ] t w o [0x2028] r e d [ ] b l u e[0x200d] g r e e n [0x0a]
+Breaks: c c c c lc c c c Lc c c c lc c c c c c c c c c c
+Whitespace: x w x w w
+Words: bs be bs be bs be bs be b
+Sentences: bs e bs e b
diff --git a/tests/breaks/two.expected b/tests/breaks/two.expected
index cea1f884..7ff48c28 100644
--- a/tests/breaks/two.expected
+++ b/tests/breaks/two.expected
@@ -1,5 +1,5 @@
-Text: g o r i l · l e s [0x0a]
-Breaks: c c c c c c c c c c Lc
-Whitespace: w w
-Words: bs e s be b
-Sentences: bs e b
+Text: g o r i l · l e s [0x0a]
+Breaks: c c c c c c c c c c c
+Whitespace: w w
+Words: bs e s be b
+Sentences: bs e b
diff --git a/tests/layouts/valid-4.expected b/tests/layouts/valid-4.expected
index d0ffe0ed..09f143f3 100644
--- a/tests/layouts/valid-4.expected
+++ b/tests/layouts/valid-4.expected
@@ -23,16 +23,14 @@ i=6, index=152, paragraph-start=1, dir=ltr ''
--- runs
-i=1, index=0, chars=29, level=0, gravity=south, flags=0, font=OMITTED, script=latin, language=en-us, 'This paragraph should ac­tual'
-i=2, index=30, chars=1, level=0, gravity=south, flags=0, font=OMITTED, script=common, language=en-us, '­'
-i=3, index=32, no run, line end
-i=4, index=32, chars=31, level=0, gravity=south, flags=0, font=OMITTED, script=latin, language=en-us, 'ly have multiple lines, unlike '
-i=5, index=63, no run, line end
-i=6, index=63, chars=28, level=0, gravity=south, flags=0, font=OMITTED, script=latin, language=en-us, 'all the other wannabe äöü pa'
-i=7, index=94, chars=1, level=0, gravity=south, flags=0, font=OMITTED, script=common, language=en-us, '­'
-i=8, index=96, no run, line end
-i=9, index=96, chars=27, level=0, gravity=south, flags=0, font=OMITTED, script=latin, language=en-us, 'ra­graph tests in this ugh '
-i=10, index=124, no run, line end
-i=11, index=124, chars=27, level=0, gravity=south, flags=0, font=OMITTED, script=latin, language=en-us, 'test-case. Grow some lines!'
-i=12, index=151, no run, line end
-i=13, index=152, no run, line end
+i=1, index=0, chars=30, level=0, gravity=south, flags=4, font=OMITTED, script=latin, language=en-us, 'This paragraph should ac­tual­'
+i=2, index=32, no run, line end
+i=3, index=32, chars=31, level=0, gravity=south, flags=0, font=OMITTED, script=latin, language=en-us, 'ly have multiple lines, unlike '
+i=4, index=63, no run, line end
+i=5, index=63, chars=29, level=0, gravity=south, flags=4, font=OMITTED, script=latin, language=en-us, 'all the other wannabe äöü pa­'
+i=6, index=96, no run, line end
+i=7, index=96, chars=27, level=0, gravity=south, flags=0, font=OMITTED, script=latin, language=en-us, 'ra­graph tests in this ugh '
+i=8, index=124, no run, line end
+i=9, index=124, chars=27, level=0, gravity=south, flags=0, font=OMITTED, script=latin, language=en-us, 'test-case. Grow some lines!'
+i=10, index=151, no run, line end
+i=11, index=152, no run, line end
diff --git a/tests/test-break.c b/tests/test-break.c
index 00bc7be0..8549b678 100644
--- a/tests/test-break.c
+++ b/tests/test-break.c
@@ -41,13 +41,15 @@ test_file (const gchar *filename, GString *string)
gsize length;
GError *error = NULL;
PangoLogAttr *attrs;
- PangoLanguage *lang;
int len;
char *p;
int i;
GString *s1, *s2, *s3, *s4;
int m;
char *test;
+ char *text;
+ PangoAttrList *attributes;
+ PangoLayout *layout;
if (!g_file_get_contents (filename, &contents, &length, &error))
{
@@ -66,9 +68,17 @@ test_file (const gchar *filename, GString *string)
len = g_utf8_strlen (test, -1) + 1;
attrs = g_new (PangoLogAttr, len);
- lang = pango_language_from_string ("en");
+ if (!pango_parse_markup (test, -1, 0, &attributes, &text, NULL, &error))
+ {
+ fprintf (stderr, "%s\n", error->message);
+ g_error_free (error);
+ return;
+ }
- pango_get_log_attrs (test, length, -1, lang, attrs, len);
+ layout = pango_layout_new (context);
+ pango_layout_set_text (layout, text, length);
+ pango_layout_set_attributes (layout, attributes);
+ pango_layout_get_log_attrs (layout, &attrs, &len);
s1 = g_string_new ("Breaks: ");
s2 = g_string_new ("Whitespace: ");
@@ -85,7 +95,7 @@ test_file (const gchar *filename, GString *string)
g_string_append_printf (s4, "%*s", (int)(m - s4->len), "");
g_string_append_printf (string, "%*s", (int)(m - strlen ("Text: ")), "");
- for (i = 0, p = test; i < len; i++, p = g_utf8_next_char (p))
+ for (i = 0, p = text; i < len; i++, p = g_utf8_next_char (p))
{
PangoLogAttr log = attrs[i];
int b = 0;
@@ -208,8 +218,10 @@ test_file (const gchar *filename, GString *string)
g_string_free (s3, TRUE);
g_string_free (s4, TRUE);
+ g_object_unref (layout);
g_free (attrs);
g_free (contents);
+ pango_attr_list_unref (attributes);
}
static gchar *
@@ -270,7 +282,7 @@ main (int argc, char *argv[])
g_test_init (&argc, &argv, NULL);
- context = pango_context_new ();
+ context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
/* allow to easily generate expected output for new test cases */
if (argc > 1)
diff --git a/tests/testiter.c b/tests/testiter.c
index de3b462f..653c4bec 100644
--- a/tests/testiter.c
+++ b/tests/testiter.c
@@ -115,12 +115,19 @@ iter_char_test (PangoLayout *layout)
if (run)
{
+ PangoFontDescription *desc;
+ char *str;
+
/* Get needed data for the GlyphString */
pango_layout_iter_get_run_extents(iter, NULL, &run_extents);
offset = run->item->offset;
rtl = run->item->analysis.level%2;
- verbose (" (current run: offset=%d,x=%d,len=%d,rtl=%d)\n",
- offset, run_extents.x, run->item->length, rtl);
+ desc = pango_font_describe (run->item->analysis.font);
+ str = pango_font_description_to_string (desc);
+ verbose (" (current run: font=%s,offset=%d,x=%d,len=%d,rtl=%d)\n",
+ str, offset, run_extents.x, run->item->length, rtl);
+ g_free (str);
+ pango_font_description_free (desc);
/* Calculate expected x result using index_to_x */
pango_glyph_string_index_to_x (run->glyphs,
diff --git a/utils/test-hyphens.txt b/utils/test-hyphens.txt
index de085d7f..65a6afc8 100644
--- a/utils/test-hyphens.txt
+++ b/utils/test-hyphens.txt
@@ -1,3 +1,3 @@
-A hy­phen­ation al­go­rithm is a set of rules, espe­ci­ally one co­di­fied for im­ple­men­tation in a com­pu­ter pro­gram, that de­ci­des at which points a word can be bro­ken over two lines with a hy­phen. For ex­am­ple, a hy­phen­ation al­go­rithm might de­cide that im­peach­ment can be broken as impeach‧ment or im‧peachment but not impe‧‍achment.
+<span allow_breaks="false">A</span> hy­phen­ation al­go­rithm is a set of rules, espe­ci­ally one co­di­fied for im­ple­men­tation in a com­pu­ter pro­gram, that de­ci­des at which points a word can be bro­ken over two lines with a hy­phen. For ex­am­ple, a hy­phen­ation al­go­rithm might de­cide that im­peach­ment can be broken as <span allow_breaks="false">impeach‧ment</span> or <span allow_breaks="false">im‧peachment</span> but not <span allow_breaks="false">impe‧achment.</span>
-One of the rea­sons for the com­plex­ity of the rules of word­break­ing is that dif­fer­ent "di­alects" of English tend to dif­fer on hy­phen­ation[ci­ta­tion needed]: Ame­rican Eng­lish tends to work on sound, but British English tends to look to the ori­gins of the word and then to sound. There are also a large num­ber of ex­cep­tions, which fur­ther com­pli­cates mat­ters.
+One of the rea­sons for the com­plex­ity of the rules of word­break­ing is that dif­fer­ent "di­alects" of English tend to dif­fer on hy­phen­ation [ci­ta­tion needed]: <span allow_breaks="false">Ame­rican</span> Eng­lish tends to work on sound, but British English tends to look to the ori­gins of the word and then to sound. There are also a large num­ber of ex­cep­tions, which fur­ther com­pli­cates mat­ters.