diff --git a/apps/vectorcraft/src/printing.rs b/apps/vectorcraft/src/printing.rs index 8f8d30a34..c9e6539a2 100644 --- a/apps/vectorcraft/src/printing.rs +++ b/apps/vectorcraft/src/printing.rs @@ -24,8 +24,9 @@ impl PrintService for SystemPrint { Some(std::sync::Arc::new(|job| SystemPrint.print(job))) } fn turns_landscape(&self) -> bool { - // `lp` doesn't turn a landscape page to the paper (macOS cuts it off on upright paper). - false + // macOS's `lp` doesn't turn a landscape page to the paper: it cuts it off on upright + // paper. craft-print turns each sheet to its own orientation on Windows. + !cfg!(target_os = "macos") } fn has_setup(&self) -> bool { true @@ -131,3 +132,14 @@ mod tests { assert_eq!(args, ["ms-settings:printers"]); } } + +#[cfg(test)] +mod turn_tests { + use super::SystemPrint; + use vectorcraft_ui_egui::print::PrintService; + + #[test] + fn only_macos_queues_need_landscape_pages_turned() { + assert_eq!(SystemPrint.turns_landscape(), !cfg!(target_os = "macos")); + } +} diff --git a/crates/engine/src/cmd/print.rs b/crates/engine/src/cmd/print.rs index a19ef1ae2..be17271c0 100644 --- a/crates/engine/src/cmd/print.rs +++ b/crates/engine/src/cmd/print.rs @@ -40,7 +40,7 @@ pub fn specs() -> Vec { "Print", [], Some("Cmd+P"), - "{preset?: name (as print.setup's: its settings instead of the document's; the saved settings stay), settings?: {…settings of print.setup} (over the document's or the preset's), path?, format?: pdf (default: a print-ready PDF) | postscript (the default for a .ps path: a PostScript file with DSC comments, %%Pages, a page per sheet with its paper size, marks, separations with their ink and halftone screen, the fixed flatness, negatives), level?: 3|2 (the PostScript language level), flattenerPreset?: \"medium\" (PostScript: the preset transparency is flattened with — high, low or a saved one, see flattener.presets.list), acknowledgeLoss?: bool (with path: write over the file the document was read from although reading it left things out), forPrinter?: bool (the PDF goes to a print queue: a page wider than tall is written upright on the paper, the art turned a quarter anticlockwise, as a printer driver turns a landscape job; macOS prints a landscape page as it is, cut off on upright paper)} print the document, one page per sheet of paper (per tile, per ink, per copy) → {pages, format, path, bytes, warnings}; no path → {dataBase64, bytes, pages, format, warnings}. Raster effects print at the document's raster effects resolution; a PDF leaves halftone screens and flatness to the output device", + "{preset?: name (as print.setup's: its settings instead of the document's; the saved settings stay), settings?: {…settings of print.setup} (over the document's or the preset's), path?, format?: pdf (default: a print-ready PDF) | postscript (the default for a .ps path: a PostScript file with DSC comments, %%Pages, a page per sheet with its paper size, marks, separations with their ink and halftone screen, the fixed flatness, negatives), level?: 3|2 (the PostScript language level), flattenerPreset?: \"medium\" (PostScript: the preset transparency is flattened with — high, low or a saved one, see flattener.presets.list), acknowledgeLoss?: bool (with path: write over the file the document was read from although reading it left things out), forPrinter?: bool (the PDF goes to a print queue: a page whose paper is turned to landscape is written upright, the art turned a quarter anticlockwise, as a printer driver turns a landscape job; macOS prints a landscape page as it is, cut off on upright paper; paper wide in Portrait and transverse pages stay as they are)} print the document, one page per sheet of paper (per tile, per ink, per copy) → {pages, format, path, bytes, warnings}; no path → {dataBase64, bytes, pages, format, warnings}. Raster effects print at the document's raster effects resolution; a PDF leaves halftone screens and flatness to the output device", has_doc, print ), diff --git a/crates/pdf/src/print/mod.rs b/crates/pdf/src/print/mod.rs index 9ef36ff2e..a8e54b324 100644 --- a/crates/pdf/src/print/mod.rs +++ b/crates/pdf/src/print/mod.rs @@ -68,8 +68,9 @@ pub struct PrintOptions { /// warnings that they are left to the device. pub postscript: bool, /// The job goes to a print queue, which puts each page on the paper as it is (macOS does - /// not turn a landscape page to the paper): a page wider than tall is written upright, the - /// art turned a quarter anticlockwise, as a printer driver turns a landscape job. + /// not turn a landscape page to the paper): a page whose paper the layout turned to landscape + /// is written upright, the art turned a quarter anticlockwise, as a printer driver turns a + /// landscape job. Paper that is wide in Portrait, and transverse pages, stay as they are. pub for_printer: bool, } @@ -392,15 +393,17 @@ pub fn plan<'a>(doc: &'a Document, opts: &PrintOptions) -> Result, plate: *plate, ink: ink.cloned(), }; - Some(if opts.for_printer { upright(sheet) } else { sheet }) + // Only the paper the layout turned: custom paper can be wide in Portrait. + let turned = l.orientation.landscape() && !set.transverse; + Some(if opts.for_printer && turned { upright(sheet) } else { sheet }) }) .collect(); let order = job.order(set); Ok(PrintPlan { plates, sheets, order, title, created, warnings: job.warnings, doc: job.doc }) } -/// `s` upright on the paper ([`PrintOptions::for_printer`]): a page wider than tall turns a -/// quarter anticlockwise, its top to the paper's left edge. +/// Landscape sheet `s` upright on the paper ([`PrintOptions::for_printer`]): a page wider than +/// tall turns a quarter anticlockwise, its top to the paper's left edge. fn upright(mut s: PlannedSheet) -> PlannedSheet { let (w, h) = s.size; if w <= h { diff --git a/crates/pdf/src/tests_print.rs b/crates/pdf/src/tests_print.rs index a37ea408e..cd1232a4a 100644 --- a/crates/pdf/src/tests_print.rs +++ b/crates/pdf/src/tests_print.rs @@ -462,6 +462,20 @@ fn for_a_printer_landscape_pages_print_upright_turned_anticlockwise() { let mut t = s; t["transverse"] = json!(true); assert_eq!(spooled(t).0, (612.0, 792.0)); + // Transverse in Portrait is wide on purpose: it stays wide. + assert_eq!(spooled(json!({"autoRotate": false, "transverse": true})).0, (792.0, 612.0)); +} + +#[test] +fn for_a_printer_paper_wide_in_portrait_stays_as_it_is() { + // A 4 × 2 in label in Portrait: the queue's media is wide too. + let d = doc(288.0, 144.0, &[(Rect::new(0.0, 0.0, 144.0, 144.0), rgb(1.0, 0.0, 0.0))]); + let v = + json!({"media": "custom", "width": 288, "height": 144, "orientation": "portrait", "autoRotate": false, "placement": {"origin": "topLeft"}}); + let opts = PrintOptions { settings: settings(v), uncompressed: true, for_printer: true, ..Default::default() }; + let p = pages(&print(&d, &opts).unwrap().bytes).remove(0); + assert_eq!(p.0, (288.0, 144.0)); + assert!(near(p.1[0].0, Rect::new(0.0, 0.0, 144.0, 144.0)), "{:?}", p.1); } #[test] diff --git a/crates/ui-egui/src/print.rs b/crates/ui-egui/src/print.rs index 1eeea2846..499f6f260 100644 --- a/crates/ui-egui/src/print.rs +++ b/crates/ui-egui/src/print.rs @@ -42,9 +42,9 @@ pub trait PrintService { fn shared_print(&self) -> Option { None } - /// Whether the system turns a page wider than tall to fit the paper. The desktop's print - /// queues put each page on the paper as it is, so their jobs are written upright - /// (`file.print`'s `forPrinter`); the browser's print dialog turns them itself. + /// Whether the system turns a landscape page to fit the paper. macOS's print queues put + /// each page on the paper as it is, so their jobs are written upright (`file.print`'s + /// `forPrinter`); Windows and the browser's print dialog turn them themselves. fn turns_landscape(&self) -> bool { true }