mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-27 03:06:57 -06:00
file.print {format: "postscript"} (the default for a .ps path) writes the
print job as Level 3 or 2 (level) PostScript instead of a PDF: DSC comments
with %%Pages the page count, one page per sheet with its paper size,
printer's marks in Registration, separations naming their ink (%%PlateColor)
with its halftone screen, a fixed flatness and film negatives. Transparency
is flattened first with flattenerPreset. The answer says which format was
written. In the app, a PostScript job is always saved, never sent to the
printer (the Print dialog's own options are unchanged).
The PDF print's layout is exposed as vectorcraft_pdf::plan (the PDF writer
uses it too); vectorcraft_eps::print draws its sheets with the EPS writer's
document walk, each sheet once however many copies print.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
66 lines
2.4 KiB
Rust
66 lines
2.4 KiB
Rust
//! Print to a PostScript file through the app: the job is saved, never sent to the printer.
|
|
|
|
use std::cell::RefCell;
|
|
use std::rc::Rc;
|
|
|
|
use serde_json::json;
|
|
use vectorcraft_engine::Session;
|
|
|
|
use crate::print::{PrintJob, PrintService, Printer};
|
|
use crate::{Services, VectorcraftApp};
|
|
|
|
/// What the app wrote: (path, bytes).
|
|
type Written = Rc<RefCell<Vec<(String, Vec<u8>)>>>;
|
|
|
|
/// A printer that counts the jobs it is sent.
|
|
struct Counting(Rc<RefCell<usize>>);
|
|
|
|
impl PrintService for Counting {
|
|
fn printers(&mut self) -> Vec<Printer> {
|
|
vec![Printer { name: "Office".into(), default: true }]
|
|
}
|
|
|
|
fn print(&mut self, _: &PrintJob) -> Result<String, String> {
|
|
*self.0.borrow_mut() += 1;
|
|
Ok("Sent".into())
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn postscript_is_saved_not_printed() {
|
|
let sent = Rc::new(RefCell::new(0));
|
|
let written: Written = Rc::default();
|
|
let w = written.clone();
|
|
let services = Services {
|
|
print: Some(Box::new(Counting(sent.clone()))),
|
|
pick_save: Some(Box::new(|pick: &crate::FilePick| Some(format!("/tmp/{}", pick.name)))),
|
|
write: Some(Box::new(move |p: &str, b: &[u8]| {
|
|
w.borrow_mut().push((p.to_string(), b.to_vec()));
|
|
Ok(())
|
|
})),
|
|
..Default::default()
|
|
};
|
|
let mut app = VectorcraftApp::new(Session::new(), services);
|
|
app.run("file.new", json!({"width": 100, "height": 80, "artboards": 2})).unwrap();
|
|
// A .ps path: PostScript, at the level asked for.
|
|
let r = app.run("file.print", json!({"path": "/tmp/job.ps", "level": 2})).unwrap();
|
|
assert_eq!((r["format"].clone(), r["printed"].clone(), r["pages"].clone()), (json!("postscript"), json!(false), json!(2)), "{r}");
|
|
// No path: a picked .ps file.
|
|
let r = app.run("file.print", json!({"format": "postscript", "settings": {"copies": 2}})).unwrap();
|
|
assert_eq!(r["pages"], 4);
|
|
let w = written.borrow();
|
|
assert_eq!(w.len(), 2);
|
|
assert_eq!(w[0].0, "/tmp/job.ps");
|
|
assert!(w[1].0.ends_with(".ps"), "{}", w[1].0);
|
|
for (_, bytes) in w.iter() {
|
|
assert!(bytes.starts_with(b"%!PS-Adobe-3.0\n"));
|
|
}
|
|
assert!(String::from_utf8_lossy(&w[0].1).contains("%%LanguageLevel: 2"));
|
|
assert_eq!(*sent.borrow(), 0, "nothing went to the printer");
|
|
drop(w);
|
|
// A PDF still goes to the printer.
|
|
app.run("file.print", json!({"settings": {"copies": 1}})).unwrap();
|
|
assert_eq!(*sent.borrow(), 1);
|
|
assert!(app.run("file.print", json!({"format": "ps2"})).is_err());
|
|
}
|