diff options
Diffstat (limited to 'pango')
-rw-r--r-- | pango/pango-break.h | 2 | ||||
-rw-r--r-- | pango/pango-item-private.h | 4 | ||||
-rw-r--r-- | pango/pango-item.c | 27 | ||||
-rw-r--r-- | pango/pango-layout.c | 52 |
4 files changed, 82 insertions, 3 deletions
diff --git a/pango/pango-break.h b/pango/pango-break.h index 5d791e27..797fefd1 100644 --- a/pango/pango-break.h +++ b/pango/pango-break.h @@ -97,6 +97,8 @@ struct _PangoLogAttr guint is_word_boundary : 1; guint break_inserts_hyphen : 1; guint break_removes_preceding : 1; + + guint reserved : 17; }; PANGO_DEPRECATED_IN_1_44 diff --git a/pango/pango-item-private.h b/pango/pango-item-private.h index ef3e8ed0..d37fc3f8 100644 --- a/pango/pango-item-private.h +++ b/pango/pango-item-private.h @@ -88,6 +88,10 @@ GList * pango_itemize_post_process_items (PangoContext PangoLogAttr *log_attrs, GList *items); +void pango_item_unsplit (PangoItem *orig, + int split_index, + int split_offset); + G_END_DECLS diff --git a/pango/pango-item.c b/pango/pango-item.c index 4b02c277..2b2664c5 100644 --- a/pango/pango-item.c +++ b/pango/pango-item.c @@ -138,7 +138,7 @@ G_DEFINE_BOXED_TYPE (PangoItem, pango_item, * Return value: new item representing text before @split_index, which * should be freed with [method@Pango.Item.free]. */ -PangoItem* +PangoItem * pango_item_split (PangoItem *orig, int split_index, int split_offset) @@ -164,6 +164,31 @@ pango_item_split (PangoItem *orig, return new_item; } +/*< private > + * pango_item_unsplit: + * @orig: the item to unsplit + * @split_index: value passed to pango_item_split() + * @split_offset: value passed to pango_item_split() + * + * Undoes the effect of a pango_item_split() call with + * the same arguments. + * + * You are expected to free the new item that was returned + * by pango_item_split() yourself. + */ +void +pango_item_unsplit (PangoItem *orig, + int split_index, + int split_offset) +{ + orig->offset -= split_index; + orig->length += split_index; + orig->num_chars += split_offset; + + if (orig->analysis.flags & PANGO_ANALYSIS_FLAG_HAS_CHAR_OFFSET) + ((PangoItemPrivate *)orig)->char_offset -= split_offset; +} + static int compare_attr (gconstpointer p1, gconstpointer p2) { diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 1a460d4c..fad92b3b 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -3525,6 +3525,29 @@ shape_tab (PangoLayoutLine *line, } } +#define DISABLE_BREAKPOINT_FLAG (1 << 16) + +static inline void +disable_breakpoint (PangoLayout *layout, + int offset) +{ + layout->log_attrs[offset].reserved |= DISABLE_BREAKPOINT_FLAG; +} + +static inline gboolean +breakpoint_is_disabled (PangoLayout *layout, + int offset) +{ + return (layout->log_attrs[offset].reserved & DISABLE_BREAKPOINT_FLAG) != 0; +} + +static void +clear_breakpoint_flags (PangoLayout *layout) +{ + for (int i = 0; i < layout->n_chars + 1; i++) + layout->log_attrs[i].reserved = 0; +} + static inline gboolean can_break_at (PangoLayout *layout, gint offset, @@ -3542,6 +3565,8 @@ can_break_at (PangoLayout *layout, if (offset == layout->n_chars) return TRUE; + else if (breakpoint_is_disabled (layout, offset)) + return FALSE; else if (wrap == PANGO_WRAP_WORD) return layout->log_attrs[offset].is_line_break; else if (wrap == PANGO_WRAP_CHAR) @@ -3943,9 +3968,9 @@ process_item (PangoLayout *layout, * the cluster here. But should be fine in practice. */ if (break_num_chars > 0 && break_num_chars < item->num_chars && layout->log_attrs[state->start_offset + break_num_chars - 1].is_white) - { + { break_width -= state->log_widths[state->log_widths_offset + break_num_chars - 1]; - } + } if (layout->wrap == PANGO_WRAP_WORD_CHAR && force_fit && break_width + break_extra_width > state->remaining_width && !retrying_with_char_breaks) { @@ -3990,7 +4015,28 @@ process_item (PangoLayout *layout, /* 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); + if (break_width > state->remaining_width && + !breakpoint_is_disabled (layout, break_num_chars) && + break_num_chars > 1) + { + /* Unsplit the item, disable the breakpoint, try again */ + + uninsert_run (line); + pango_item_free (new_item); + pango_item_unsplit (item, length, break_num_chars); + + disable_breakpoint (layout, break_num_chars); + + num_chars = item->num_chars; + width = orig_width; + break_num_chars = num_chars; + break_width = width; + + goto retry_break; + } + state->remaining_width -= break_width; state->log_widths_offset += break_num_chars; @@ -4598,6 +4644,8 @@ pango_layout_check_lines (PangoLayout *layout) } while (!done); + clear_breakpoint_flags (layout); + g_free (state.log_widths); g_list_free_full (state.baseline_shifts, g_free); |