diff --git a/bidi/src/lib.rs b/bidi/src/lib.rs index c8e16e842..b4c61f3c5 100644 --- a/bidi/src/lib.rs +++ b/bidi/src/lib.rs @@ -187,19 +187,34 @@ impl BidiContext { } pub fn reordered_runs(&self, line_range: Range) -> Vec { + // reorder_line's `level` result includes entries that were + // removed_by_x9() but `reordered` does NOT (for compatibility with + // the UCD test suite). + // We need to account for that when we reorder the levels here! let (levels, reordered) = self.reorder_line(line_range); + let mut reordered_levels = vec![Level(NO_LEVEL); reordered.len()]; + + for (vis_idx, &log_idx) in reordered.iter().enumerate() { + reordered_levels[vis_idx] = levels[log_idx]; + } + + reordered_levels.retain(|l| !l.removed_by_x9()); + let mut runs = vec![]; let mut idx = 0; - while idx < levels.len() { - let len = span_len(idx, &levels); - let level = levels[idx]; + while idx < reordered_levels.len() { + let len = span_len(idx, &reordered_levels); + let level = reordered_levels[idx]; if !level.removed_by_x9() { + let idx_range = idx..idx + len; + let start = reordered[idx_range.clone()].iter().min().unwrap(); + let end = reordered[idx_range.clone()].iter().max().unwrap(); runs.push(ReorderedRun { direction: level.direction(), level, - range: idx..idx + len, - indices: reordered[idx..idx + len].to_vec(), + range: *start..*end + 1, + indices: reordered[idx_range].to_vec(), }); } idx += len; diff --git a/termwiz/src/cellcluster.rs b/termwiz/src/cellcluster.rs index 1520cacf5..7f263e309 100644 --- a/termwiz/src/cellcluster.rs +++ b/termwiz/src/cellcluster.rs @@ -174,14 +174,19 @@ impl CellCluster { } context.resolve_paragraph(¶graph, hint); - for run in context.runs() { + for run in context.reordered_runs(0..paragraph.len()) { let mut text = String::with_capacity(run.range.end - run.range.start); let mut byte_to_cell_idx = vec![]; let mut byte_to_cell_width = vec![]; let mut width = 0usize; let mut first_cell_idx = None; - for cp_idx in run.indices() { + // Note: if we wanted the actual bidi-re-ordered + // text we should iterate over run.indices here, + // however, cluster.text will be fed into harfbuzz + // and that requires the original logical order + // for the text, so we look at run.range instead. + for cp_idx in run.range.clone() { let cp = paragraph[cp_idx]; text.push(cp);