diff options
author | Matthias Clasen <mclasen@redhat.com> | 2021-11-14 21:26:59 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2021-11-15 08:38:45 -0500 |
commit | ff08cc43da46b5ea339a2c700fe669bed2ddc7b9 (patch) | |
tree | d22c9ac95f1b5ba7bca12015ce9af66a28e6c42b /pango/pango-layout.c | |
parent | 3a566950b516386b25fa028bee73d524dd9ada92 (diff) | |
download | pango-ff08cc43da46b5ea339a2c700fe669bed2ddc7b9.tar.gz |
Go back to an array for disabled breakpoints
It turns out that we do need to look for longer breakpoints
after all if we want to find optimal solutions.
Diffstat (limited to 'pango/pango-layout.c')
-rw-r--r-- | pango/pango-layout.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 656bfb18..f0795a62 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -3897,7 +3897,7 @@ process_item (PangoLayout *layout, int orig_width = width; int break_extra_width = 0; gboolean retrying_with_char_breaks = FALSE; - int last_break_char = item->num_chars; + gboolean *break_disabled; if (processing_new_item) { @@ -3910,6 +3910,9 @@ process_item (PangoLayout *layout, pango_glyph_item_get_logical_widths (&glyph_item, layout->text, state->log_widths); } + break_disabled = g_alloca (sizeof (gboolean) * (item->num_chars + 1)); + memset (break_disabled, 0, sizeof (gboolean) * (item->num_chars + 1)); + retry_break: /* break_extra_width gets normally set from find_break_extra_width inside @@ -3947,21 +3950,33 @@ process_item (PangoLayout *layout, /* See how much of the item we can stuff in the line. */ width = 0; - for (num_chars = 0; num_chars < last_break_char; num_chars++) + for (num_chars = 0; num_chars < item->num_chars; num_chars++) { extra_width = find_break_extra_width (layout, state, num_chars); - if (MIN (width + extra_width, width) > state->remaining_width && break_num_chars < item->num_chars) + /* We don't want to walk the entire item if we can help it, but + * we need to keep going at least until we've found a breakpoint + * that 'works' (as in, doesn't overflow the budget we have), + * and there is no hope of finding a better one. + * + * We rely on the fact that MIN(width + extra_width, width) is + * monotonically increasing. + */ + if (MIN (width + extra_width, width) > state->remaining_width && + break_width + break_extra_width <= state->remaining_width && + break_num_chars < item->num_chars) { break; } /* If there are no previous runs we have to take care to grab at least one char. */ - if (can_break_at (layout, state->start_offset + num_chars, retrying_with_char_breaks) && + if (!break_disabled[num_chars] && + can_break_at (layout, state->start_offset + num_chars, retrying_with_char_breaks) && (num_chars > 0 || line->runs)) { - if (width + extra_width <= state->remaining_width || - break_num_chars >= last_break_char) + /* If we had a breakpoint already, we only want to replace it with a better one. */ + if (break_num_chars == item->num_chars || + width + extra_width <= MAX (break_width + break_extra_width, state->remaining_width)) { break_num_chars = num_chars; break_width = width; @@ -3975,7 +3990,6 @@ process_item (PangoLayout *layout, if (layout->wrap == PANGO_WRAP_WORD_CHAR && force_fit && break_width + break_extra_width > state->remaining_width && !retrying_with_char_breaks) { retrying_with_char_breaks = TRUE; - last_break_char = item->num_chars; break_num_chars = item->num_chars; width = orig_width; break_width = width; @@ -4026,8 +4040,7 @@ process_item (PangoLayout *layout, break_width -= state->log_widths[state->log_widths_offset + break_num_chars - 1]; if (break_width > state->remaining_width && - break_num_chars < last_break_char && - break_num_chars > 1) + !break_disabled[break_num_chars]) { /* Unsplit the item, disable the breakpoint, try again */ @@ -4035,9 +4048,10 @@ process_item (PangoLayout *layout, pango_item_free (new_item); pango_item_unsplit (item, length, break_num_chars); - last_break_char = break_num_chars; + break_disabled[break_num_chars] = TRUE; width = orig_width; break_width = width; + break_num_chars = item->num_chars; goto retry_break; } |