mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-24 10:08:00 -06:00
fix(edit): setting a paragraph's width no longer panics on text larger than a page (#4110)
rewrite_block clamps a requested paragraph width between the text's size in user space (size * k) and the largest page PDF allows (14 400 pt). f64::clamp panics when its minimum is the larger, so text set above 14 400 pt crashed the app as soon as its paragraph was given a width. The size comes from the file (`20000 Tf`, or `1 Tf` scaled up by `Tm`) or from the request (the automation tools pass `size` through). The lower bound is now capped at 14 400 pt too, so such a paragraph gets the widest width allowed. `f64::min` also turns a NaN size into the cap. Test: a 20000 pt Tf, a 1 pt Tf scaled 20000x by Tm, and a requested size of 20000 pt each take a width of 200 without panicking (all three panicked before). Reported-by: BS.ehlas.cz Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
co-authored by
Brandon Thomas
parent
b174b12b0e
commit
75207dc8ed
@@ -6356,6 +6356,24 @@ fn reading_keeps_dotted_leader_entries_whole_and_in_order() {
|
||||
);
|
||||
}
|
||||
|
||||
/// Text set larger than the widest page PDF allows (14 400 pt) panicked when its paragraph was given
|
||||
/// a width: the width is clamped between the font size and 14 400 pt, and `f64::clamp` panics when
|
||||
/// its minimum is the larger. The width is now capped at 14 400 pt whatever the font size: from the
|
||||
/// file (`Tf`, or a small `Tf` scaled up by `Tm`) or asked for (the automation tools pass it through).
|
||||
#[test]
|
||||
fn width_on_a_paragraph_set_larger_than_a_page_is_capped_not_a_panic() {
|
||||
let wide = text::BlockStyle { width: Some(200.0), ..Default::default() };
|
||||
let huge = text::BlockStyle { size: Some(20_000.0), width: Some(200.0), ..Default::default() };
|
||||
for (content, style) in [
|
||||
("BT /F2 20000 Tf 72 700 Td (ab) Tj ET", &wide),
|
||||
("BT /F2 1 Tf 20000 0 0 20000 72 700 Tm (ab) Tj ET", &wide),
|
||||
("BT /F2 12 Tf 72 700 Td (ab) Tj ET", &huge),
|
||||
] {
|
||||
let mut doc = text_page(content);
|
||||
text::rewrite_block(&mut doc, 0, 0, None, style).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn added_text_is_wrapped_once_per_write() {
|
||||
let mut doc = fixture();
|
||||
|
||||
@@ -2780,8 +2780,9 @@ fn rewrite_block_from(
|
||||
// A paragraph keeps its width (or takes the one asked for); a single line grows to the right
|
||||
// (to the left when right-to-left), up to the page's margin.
|
||||
let width = match style.width {
|
||||
// Capped at the largest page PDF allows (14 400 pt).
|
||||
Some(w) if w.is_finite() => w.clamp(size * k, 14_400.0),
|
||||
// Capped at the largest page PDF allows (14 400 pt), even for text set larger than that
|
||||
// (`clamp` panics when its minimum is the larger, or NaN).
|
||||
Some(w) if w.is_finite() => w.clamp((size * k).min(14_400.0), 14_400.0),
|
||||
Some(_) => return Err(EditError::Invalid("the paragraph's width must be a number".into())),
|
||||
// Turned text: the page's margins are along another axis. A single line grows (below).
|
||||
None if !upright => (frame[2] - frame[0]).max(size * k),
|
||||
|
||||
Reference in New Issue
Block a user