Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions src/layout/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,12 +391,23 @@ impl Engine<'_> {
}

// Absolute and minimum widths may claim more than the page;
// scale everything down proportionally so the table never
// overflows horizontally.
// scale columns down, preferably the ones with slack, so
// the table never overflows horizontally.
let used: f32 = widths.iter().sum();
if used > total && used > 0.0 {
for width in &mut widths {
*width *= total / used;
let floor: Vec<f32> = (0..columns).map(|c| widths[c].min(min[c])).collect();
let floor_total: f32 = floor.iter().sum();
let slack_total = used - floor_total;
if floor_total < total && slack_total > 0.0 {
let excess = used - total;
for c in 0..columns {
widths[c] -= excess * (widths[c] - floor[c]) / slack_total;
}
} else {
// No slack anywhere, fall back to a uniform scale
for width in &mut widths {
*width *= total / used;
}
}
}

Expand Down
49 changes: 49 additions & 0 deletions src/layout/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,55 @@ fn auto_column_header_words_survive_content_width_scaling() {
}
}

#[test]
fn auto_columns_keep_their_minimum_width_when_a_cell_overflows() {
let fonts = test_fonts();
let theme = Theme::default();
let engine = Engine::new(&fonts, &theme);
let style = TableStyle {
columns: ColumnWidths::custom([
ColumnWidth::Auto,
ColumnWidth::Fraction(1),
ColumnWidth::Auto,
]),
..TableStyle::data()
};

let overflowing_words = [
"The-mantis-shrimp-Stomatopoda-Malacostraca-crustaceans-trinocular-depth-perception-circular-polarised-light",
"Odontodactylus-scyllarus-peacock-mantis-shrimp-smasher-appendage-acceleration-cavitation-bubble-collapse",
"Gonodactylus-smithii-spearer-burrow-defended-territory-aggressive-visual-signal-display-behaviour-noted-daily",
"Lysiosquillina-maculata-zebra-mantis-shrimp-monogamous-pair-bonding-burrow-sharing-lifetime-partnership",
"Hemisquilla-californiensis-giant-mantis-shrimp-bioluminescent-fluorescent-carapace-markings-detected-clearly",
];

for word in overflowing_words {
let mut doc = Textris::new();
doc.table_styled(
&style,
["index", "name", "final score value"],
[["123", word, "12345"]],
);
let d = doc.build();
let crate::model::Block::Table(t) = &d.blocks[0] else {
panic!("expected a table");
};
let total = theme.page.content_width();
let widths = engine.column_widths(t, t.columns(), total);

// Auto columns must stay wide enough to hold their widest word
for col in [0, 2] {
let (min_content_width, _) = engine.column_metrics(t, col);
assert!(
widths[col] >= min_content_width + 2.0 * theme.table.inset_x - 0.01,
"{word:?}: column {col} ({}) should fit its own widest word (min {})",
widths[col],
min_content_width + 2.0 * theme.table.inset_x
);
}
}
}

#[test]
fn column_alignment_places_cell_text_left_center_and_right() {
use crate::{
Expand Down
Loading