summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2019-07-16 23:10:20 +0000
committerMatthias Clasen <mclasen@redhat.com>2019-07-16 23:10:20 +0000
commit8c7acb646dfbebd71db5a7310d2dc5dc7412dcfc (patch)
tree853af11169cb56789f583187d6d293bd2f4148c6
parentc5aeaba0816f8adb6557d5306b65e85c254b400c (diff)
parentcc9b0912566b7c3bd4c1b31b5e6dd8532f1794c1 (diff)
downloadpango-8c7acb646dfbebd71db5a7310d2dc5dc7412dcfc.tar.gz
Merge branch 'tailor-break' into 'master'
Tailor break See merge request GNOME/pango!86
-rw-r--r--docs/pango-sections.txt2
-rw-r--r--pango/break.c76
-rw-r--r--pango/pango-break.h12
-rw-r--r--pango/pango-layout.c82
4 files changed, 108 insertions, 64 deletions
diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt
index e20c917a..496db41a 100644
--- a/docs/pango-sections.txt
+++ b/docs/pango-sections.txt
@@ -23,6 +23,7 @@ pango_break
pango_get_log_attrs
pango_find_paragraph_boundary
pango_default_break
+pango_tailor_break
PangoLogAttr
<SUBSECTION>
@@ -71,6 +72,7 @@ PANGO_CONTEXT_CLASS
PANGO_IS_CONTEXT
PANGO_IS_CONTEXT_CLASS
PANGO_CONTEXT_GET_CLASS
+PANGO_TYPE_ITEM
<SUBSECTION Private>
pango_context_get_type
diff --git a/pango/break.c b/pango/break.c
index 11a1e34a..8066fca0 100644
--- a/pango/break.c
+++ b/pango/break.c
@@ -146,13 +146,11 @@ typedef enum
* @attrs: logical attributes to fill in
* @attrs_len: size of the array passed as @attrs
*
- * This is the default break algorithm, used if no language
- * engine overrides it. Normally you should use pango_break()
- * instead. Unlike pango_break(),
- * @analysis can be %NULL, but only do that if you know what
- * you're doing. If you need an analysis to pass to pango_break(),
- * you need to pango_itemize(). In most cases however you should
- * simply use pango_get_log_attrs().
+ * This is the default break algorithm. It applies Unicode
+ * rules without language-specific tailoring, therefore
+ * the @analyis argument is unused and can be %NULL.
+ *
+ * See pango_tailor_break() for language-specific breaks.
**/
void
pango_default_break (const gchar *text,
@@ -1604,8 +1602,10 @@ tailor_break (const gchar *text,
* @attrs_len: size of the array passed as @attrs
*
* Determines possible line, word, and character breaks
- * for a string of Unicode text with a single analysis. For most
- * purposes you may want to use pango_get_log_attrs().
+ * for a string of Unicode text with a single analysis.
+ * For most purposes you may want to use pango_get_log_attrs().
+ *
+ * Deprecated: 1.44: Use pango_default_break() and pango_tailor_break()
*/
void
pango_break (const gchar *text,
@@ -1721,6 +1721,43 @@ pango_find_paragraph_boundary (const gchar *text,
*next_paragraph_start = start - text;
}
+/**
+ * pango_tailor_break:
+ * @text: text to process. Must be valid UTF-8
+ * @length: length in bytes of @text
+ * @analysis: #PangoAnalysis structure from pango_itemize() for @text
+ * @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
+ *
+ * Apply language-specific tailoring to the breaks in
+ * @log_attrs, which are assumed to have been produced
+ * by pango_default_break().
+ */
+void
+pango_tailor_break (const char *text,
+ int length,
+ PangoAnalysis *analysis,
+ 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 tailored, we enforce some of the attrs from before
+ * tailoring at the boundary
+ */
+
+ start->backspace_deletes_character = attr_before.backspace_deletes_character;
+
+ start->is_line_break |= attr_before.is_line_break;
+ start->is_mandatory_break |= attr_before.is_mandatory_break;
+ start->is_cursor_position |= attr_before.is_cursor_position;
+ }
+}
+
static int
tailor_segment (const char *range_start,
const char *range_end,
@@ -1734,22 +1771,11 @@ tailor_segment (const char *range_start,
chars_in_range = pango_utf8_strlen (range_start, range_end - range_start);
- if (tailor_break (range_start,
- range_end - range_start,
- analysis,
- start,
- chars_in_range + 1))
- {
- /* if tailored, we enforce some of the attrs from before tailoring at
- * the boundary
- */
-
- start->backspace_deletes_character = attr_before.backspace_deletes_character;
-
- start->is_line_break |= attr_before.is_line_break;
- start->is_mandatory_break |= attr_before.is_mandatory_break;
- start->is_cursor_position |= attr_before.is_cursor_position;
- }
+ pango_tailor_break (range_start,
+ range_end - range_start,
+ analysis,
+ start,
+ chars_in_range + 1);
return chars_in_range;
}
diff --git a/pango/pango-break.h b/pango/pango-break.h
index b035506e..4e1db0bc 100644
--- a/pango/pango-break.h
+++ b/pango/pango-break.h
@@ -100,10 +100,7 @@ struct _PangoLogAttr
guint is_word_boundary : 1;
};
-/* Determine information about cluster/word/line breaks in a string
- * of Unicode text.
- */
-PANGO_AVAILABLE_IN_ALL
+PANGO_DEPRECATED_IN_1_44
void pango_break (const gchar *text,
int length,
PangoAnalysis *analysis,
@@ -136,6 +133,13 @@ void pango_default_break (const gchar *text,
PangoLogAttr *attrs,
int attrs_len);
+PANGO_AVAILABLE_IN_1_44
+void pango_tailor_break (const gchar *text,
+ int length,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs,
+ int attrs_len);
+
G_END_DECLS
#endif /* __PANGO_BREAK_H__ */
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index e0725adc..21897e29 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -3958,51 +3958,61 @@ process_line (PangoLayout *layout,
state->line_start_offset = state->start_offset;
}
+static gboolean
+can_break_together (PangoAnalysis *analysis1,
+ PangoAnalysis *analysis2)
+{
+ return analysis1->level == analysis2->level &&
+ analysis1->script == analysis2->script &&
+ analysis1->language == analysis2->language;
+}
+
static void
get_items_log_attrs (const char *text,
+ int length,
GList *items,
PangoLogAttr *log_attrs,
- int para_delimiter_len)
+ int log_attrs_len)
{
int offset = 0;
int index = 0;
+ int num_bytes = 0;
+ int num_chars = 0;
+ PangoAnalysis analysis = { NULL };
+ GList *l;
- while (items)
- {
- PangoItem tmp_item = *(PangoItem *)items->data;
-
- /* Accumulate all the consecutive items that match in language
- * characteristics, ignoring font, style tags, etc.
- */
- while (items->next)
- {
- PangoItem *next_item = items->next->data;
-
- /* FIXME: Handle language tags */
- tmp_item.length += next_item->length;
- tmp_item.num_chars += next_item->num_chars;
+ analysis.level = -1;
- items = items->next;
- }
+ pango_default_break (text, length, &analysis, log_attrs, log_attrs_len);
- /* Break the paragraph delimiters with the last item */
- if (items->next == NULL)
- {
- tmp_item.num_chars += pango_utf8_strlen (text + index + tmp_item.length, para_delimiter_len);
- tmp_item.length += para_delimiter_len;
- }
-
- /* XXX This is wrong. we should call pango_default_break on the entire
- * layout text and then tailor_break on each language change, like
- * pango_get_log_attrs does.
- */
- pango_break (text + index, tmp_item.length, &tmp_item.analysis,
- log_attrs + offset, tmp_item.num_chars + 1);
+ for (l = items; l; l = l->next)
+ {
+ PangoItem *item = l->data;
- offset += tmp_item.num_chars;
- index += tmp_item.length;
+ if (l == items)
+ {
+ analysis = item->analysis;
+ index = item->offset;
+ offset = 0;
+ }
- items = items->next;
+ 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;
+ }
}
}
@@ -4243,9 +4253,11 @@ pango_layout_check_lines (PangoLayout *layout)
if (no_break_attrs)
apply_no_break_attributes (state.items, no_break_attrs);
- get_items_log_attrs (start, state.items,
+ get_items_log_attrs (start,
+ delimiter_index + delim_len,
+ state.items,
layout->log_attrs + start_offset,
- delim_len);
+ layout->n_chars + 1 - start_offset);
state.base_dir = base_dir;
state.line_of_par = 1;