mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-24 10:08:00 -06:00
M12: spaces alone stay on an XFA text line
A word of spaces alone draws nothing, but after a word whose own trailing space ran past the box it failed the fit test and opened a blank line, so the text measured a line taller than it draws. Such words now always stay on the line, keeping their width.
This commit is contained in:
@@ -2097,6 +2097,10 @@ fn a_space_at_the_end_of_a_line_does_not_count_when_fitting_it() {
|
||||
let spans = draw_spans(&one_draw("a. DATE ", w, "left"));
|
||||
let baselines: std::collections::BTreeSet<i64> = spans.iter().map(|s| (s.baseline * 100.0).round() as i64).collect();
|
||||
assert_eq!(baselines.len(), 1, "{spans:?}");
|
||||
// Nor do they add a blank line: the text measures as tall as without them.
|
||||
let face = text::Face::of(&Font { typeface: "Arial".into(), size: 10.0, ..Font::default() });
|
||||
let height = |t: &str| text::measure_height(&text::plain(t), w, &Para::default(), &face, &|_| String::new());
|
||||
assert_eq!(height("a. DATE "), height("a. DATE"));
|
||||
// Text that is wider than the box still wraps.
|
||||
let spans = draw_spans(&one_draw("a. DATES ", w, "left"));
|
||||
let baselines: std::collections::BTreeSet<i64> = spans.iter().map(|s| (s.baseline * 100.0).round() as i64).collect();
|
||||
|
||||
@@ -204,9 +204,12 @@ pub fn layout(rich: &RichText, rect: Rect, para: &Para, base: &Face, embed: &dyn
|
||||
let mut first_in_para = true;
|
||||
let indent = |first: bool| if first { para.text_indent.max(0.0) } else { 0.0 };
|
||||
for w in ws {
|
||||
// A word fits when what it draws does: the spaces after it would end the line.
|
||||
// A word fits when what it draws does: the spaces after it would end the line. Spaces
|
||||
// alone draw nothing, so they always stay on the line (keeping their width, so a word
|
||||
// after them still starts past them).
|
||||
let ink = ink_width(&w);
|
||||
let fits = line.width + ink <= avail - indent(line.first) || line.words.is_empty() && ink <= avail - indent(line.first);
|
||||
let blank = w.text.trim_end_matches(' ').is_empty();
|
||||
let fits = blank || line.width + ink <= avail - indent(line.first) || line.words.is_empty() && ink <= avail - indent(line.first);
|
||||
if !fits && !line.words.is_empty() {
|
||||
let done = std::mem::replace(&mut line, Line { words: Vec::new(), width: 0.0, size: base.size, first: false });
|
||||
lines.push((done, p.h_align));
|
||||
|
||||
Reference in New Issue
Block a user