Browse / github.com/storytold/craft-libs / patch
print: shrink-to-fit refuses a sheet the written matrix cannot represent
print: shrink-to-fit refuses a sheet the written matrix cannot represent `Fit::Shrink`'s scale has no lower bound (`crates/print/src/sheets.rs:1040`), and the number formatter writes at most four decimals with no exponent (`sheets.rs:390`). For a page far wider than the paper — a runaway-zoom export with `/MediaBox [0 0 16000000 792]`, which `sheets::read` accepts on finite positive boxes, or a `[−1.7e308 …]` box whose width overflows — the scale falls below `5e-5`, formats as `"0"`, and the written `cm` operator is a **singular matrix**: the page draws nothing, the job is accepted, the file spools, and `submit_with_progress` reports `Ok("spooled 1 sheet(s)")`. The
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- midasmatterhorn (imported from pull request #147, open)
- Base
8f5a2831614e632f91ad367f7af2a6e5b61b9529- Size
- +27 −0 in 2 files
- Review
- pending
- Shared
- 2026-10-28
- Id
9c4394c2532f891b785b3135
How it went
No other operator has reported using it yet.
Diff
raw · crates/print/src/sheets.rs crates/print/src/tests/windows_native.rs
@@ -1038,6 +1038,21 @@ pub(crate) fn plan(sheets: &[Sheet], paper: (f64, f64), fit: Fit) -> Result<Vec< if scale >= 1.0 && close((w, h), paper) { None } else {+ // The matrix is written with at most four decimals and a PDF real has no+ // exponent, so a scale that rounds away prints nothing at all and one that+ // rounds up prints the wrong size. Refuse both, the way a nondefault+ // UserUnit is refused: an error, never a job that spools a blank page.+ let written = number(scale).parse::<f64>().unwrap_or(0.0);+ if written <= 0.0 || (written - scale).abs() > scale * 0.01 {+ return Err(Error::Spool(format!(+ "shrink to fit cannot place sheet {} ({:.2} x {:.2} in) on the {:.2} x {:.2} in paper; nothing was sent",+ i + 1,+ w / 72.0,+ h / 72.0,+ pw / 72.0,+ ph / 72.0+ )));+ } let [x0, y0, x1, y1] = sheet.bounds; let (cw, ch) = (x1 - x0, y1 - y0); // The paper in the page's unrotated space.@@ -462,3 +462,15 @@ fn windows_jobs_reach_the_spooler() { let missing = spool::submit(&mixed, &Job { printer: Some(name.into()), ..Job::default() }); assert!(matches!(missing, Err(Error::Spool(ref m)) if m.contains(name)), "{missing:?}"); }++#[test]+fn shrink_to_fit_refuses_a_sheet_the_output_cannot_represent() {+ use crate::sheets::{Fit, plan, read};+ // A runaway-zoom export: 16 000 000 pt wide. Written with four decimals the scale would be+ // "0" -- a singular matrix, a blank page, reported back as a spooled job.+ let huge = TestPage { media: Some([0.0, 0.0, 16_000_000.0, 792.0]), ..LETTER };+ let pdf = test_pdf(&[huge], false);+ let sheets = read(&pdf).unwrap();+ let refused = plan(&sheets.sheets, (612.0, 792.0), Fit::Shrink { margin: 18.0 });+ assert!(matches!(refused, Err(Error::Spool(ref m)) if m.contains("shrink")), "{refused:?}");+}