Merge pull request #471 from hojjatabdollahi/hojjat/fix-bidi-zw
Fix aggressive ellipsizing
This commit is contained in:
parent
cd1d3aa1ef
commit
e83bd7f7bf
4 changed files with 145 additions and 26 deletions
102
src/shape.rs
102
src/shape.rs
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
FontSystem, Hinting, LayoutGlyph, LayoutLine, Metrics, Wrap,
|
||||
};
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::{format, vec, vec::Vec};
|
||||
use alloc::{boxed::Box, format, vec, vec::Vec};
|
||||
|
||||
use alloc::collections::VecDeque;
|
||||
use core::cmp::{max, min};
|
||||
|
|
@ -1482,6 +1482,52 @@ impl ShapeLine {
|
|||
vl.spaces += number_of_blanks;
|
||||
}
|
||||
|
||||
fn remaining_content_exceeds(
|
||||
spans: &[ShapeSpan],
|
||||
font_size: f32,
|
||||
span_index: usize,
|
||||
word_idx: usize,
|
||||
word_count: usize,
|
||||
starting_word_index: usize,
|
||||
direction: LayoutDirection,
|
||||
congruent: bool,
|
||||
start_span: usize,
|
||||
span_count: usize,
|
||||
threshold: f32,
|
||||
) -> bool {
|
||||
let mut acc: f32 = 0.0;
|
||||
|
||||
// Remaining words in the current span
|
||||
let word_range: Box<dyn Iterator<Item = usize>> = match (direction, congruent) {
|
||||
(LayoutDirection::Forward, true) => Box::new(word_idx + 1..word_count),
|
||||
(LayoutDirection::Forward, false) => Box::new(0..word_idx),
|
||||
(LayoutDirection::Backward, true) => Box::new(starting_word_index..word_idx),
|
||||
(LayoutDirection::Backward, false) => Box::new(word_idx + 1..word_count),
|
||||
};
|
||||
for wi in word_range {
|
||||
acc += spans[span_index].words[wi].width(font_size);
|
||||
if acc > threshold {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remaining spans
|
||||
let span_range: Box<dyn Iterator<Item = usize>> = match direction {
|
||||
LayoutDirection::Forward => Box::new(span_index + 1..span_count),
|
||||
LayoutDirection::Backward => Box::new(start_span..span_index),
|
||||
};
|
||||
for si in span_range {
|
||||
for w in &spans[si].words {
|
||||
acc += w.width(font_size);
|
||||
if acc > threshold {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// This will fit as much as possible in one line
|
||||
/// If forward is false, it will fit as much as possible from the end of the spans
|
||||
/// it will stop when it gets to "start".
|
||||
|
|
@ -1582,24 +1628,20 @@ impl ShapeLine {
|
|||
&& (
|
||||
// if this word doesn't fit, then we have an overflow
|
||||
(total_w + word_range_width + word_width > max_width)
|
||||
// otherwise if this is not the last word of the last span
|
||||
// and we can't fit the ellipsis
|
||||
||(
|
||||
!(match (direction, congruent) {
|
||||
(LayoutDirection::Forward, true) => {
|
||||
(span_index == span_count - 1) && (word_idx == word_count - 1)
|
||||
}
|
||||
(LayoutDirection::Forward, false) => (span_index == span_count - 1) && (word_idx == 0),
|
||||
(LayoutDirection::Backward, true) => {
|
||||
(span_index == start.span) && (word_idx == starting_word_index)
|
||||
}
|
||||
(LayoutDirection::Backward, false) => {
|
||||
(span_index == start.span) && (word_idx == word_count - 1)
|
||||
}
|
||||
})
|
||||
|
||||
&& total_w + word_range_width + word_width + ellipsis_w > max_width
|
||||
)
|
||||
|| (Self::remaining_content_exceeds(
|
||||
spans,
|
||||
font_size,
|
||||
span_index,
|
||||
word_idx,
|
||||
word_count,
|
||||
starting_word_index,
|
||||
direction,
|
||||
congruent,
|
||||
start.span,
|
||||
span_count,
|
||||
ellipsis_w,
|
||||
) && total_w + word_range_width + word_width + ellipsis_w
|
||||
> max_width)
|
||||
)
|
||||
};
|
||||
|
||||
|
|
@ -1739,6 +1781,27 @@ impl ShapeLine {
|
|||
ellipsis_w: f32,
|
||||
) {
|
||||
assert!(matches!(ellipsize, Ellipsize::Middle(_)));
|
||||
|
||||
// First check if all content fits without any ellipsis.
|
||||
{
|
||||
let mut test_line = VisualLine::default();
|
||||
self.layout_spans(
|
||||
&mut test_line,
|
||||
font_size,
|
||||
spans,
|
||||
start_opt,
|
||||
rtl,
|
||||
Some(width),
|
||||
Ellipsize::End(EllipsizeHeightLimit::Lines(1)),
|
||||
ellipsis_w,
|
||||
LayoutDirection::Forward,
|
||||
);
|
||||
if !test_line.ellipsized && test_line.w <= width {
|
||||
*current_visual_line = test_line;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let mut starting_line = VisualLine::default();
|
||||
self.layout_spans(
|
||||
&mut starting_line,
|
||||
|
|
@ -1848,6 +1911,7 @@ impl ShapeLine {
|
|||
}
|
||||
_ => {
|
||||
// everything fit in the forward pass
|
||||
log::warn!("This should be unreachable!");
|
||||
current_visual_line.ranges = starting_line.ranges;
|
||||
current_visual_line.w = starting_line.w;
|
||||
current_visual_line.spaces = starting_line.spaces;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue