From 6d8f0fb36e2cb3083f1175a8e7d3b21dce772c57 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sat, 7 Dec 2024 00:39:53 +1300 Subject: [PATCH] Prevent inline boxes from being duplicated when the line ends with an inline box. --- parley/src/layout/line/greedy.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/parley/src/layout/line/greedy.rs b/parley/src/layout/line/greedy.rs index 16eff815..201e5aa1 100644 --- a/parley/src/layout/line/greedy.rs +++ b/parley/src/layout/line/greedy.rs @@ -726,6 +726,7 @@ fn try_commit_line( // Iterate over the items to commit // println!("\nCOMMIT LINE"); + let mut last_item_kind = LayoutItemKind::TextRun; for (i, item) in items_to_commit.iter().enumerate() { // println!("i = {} index = {} {:?}", i, item.index, item.kind); @@ -745,6 +746,8 @@ fn try_commit_line( cluster_range: 0..0, text_range: 0..0, }); + + last_item_kind = item.kind; } LayoutItemKind::TextRun => { let run_data = &layout.data.runs[item.index]; @@ -768,6 +771,8 @@ fn try_commit_line( continue; } + last_item_kind = item.kind; + // Push run to line let run = Run::new(layout, 0, 0, run_data, None); let text_range = if run_data.cluster_range.is_empty() { @@ -825,10 +830,21 @@ fn try_commit_line( }); // Reset state for the new line + state.num_spaces = 0; state.clusters.start = state.clusters.end; state.clusters.end += 1; - state.items.start = state.items.end.saturating_sub(1); - state.num_spaces = 0; + + state.items.start = match last_item_kind { + // For text runs, the first item of line N+1 needs to be the SAME as + // the last item for line N. This is because the item (if it a text run + // may be split across the two lines with some clusters in line N and some + // in line N+1). The item is later filtered out (see `continue` in loop above) + // if there are not actually any clusters in line N+1. + LayoutItemKind::TextRun => state.items.end.saturating_sub(1), + // Inline boxes cannot be spread across multiple lines, so we should set + // the first item of line N+1 to be the item AFTER the last item in line N. + LayoutItemKind::InlineBox => state.items.end, + }; true }