mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-15 11:16:25 +00:00
Import PDF: linked pages on their trim boxes keep the bleed between artboards
Linked pages on their trim boxes were spaced by the 36 pt gap alone, so with a large bleed one page's bleed box reached into the next artboard and a page export could show part of its neighbor. The artboards are now laid out once the document's bleed is known, 36 pt apart plus the bleed on both sides: the document's bleed, or a page's own bleed box where it reaches farther.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -221,7 +221,7 @@ fn page_options(page: usize, o: &LoadOptions) -> ImportOptions {
|
||||
/// a PDF-compatible `.ai` asked for its crop box gets its trim box, as it opens), in a row from the
|
||||
/// left with the gap a PDF's artboards open with, and a layer named after the page. On its trim box,
|
||||
/// a page shows its bleed box round the artboard, and the document's bleed is the pages' bleed (the
|
||||
/// widest on each side). The document opens
|
||||
/// widest on each side); the artboards are then the gap apart plus the bleed on both sides. The document opens
|
||||
/// in CMYK when most of the pages read in CMYK, unless `o.color_mode` names a mode. Refused without a
|
||||
/// path, for any other file, with a password (a linked page is read again without one), with
|
||||
/// `textAs: outlines` (a linked page shows the file's own type) and for a file over
|
||||
@@ -262,8 +262,11 @@ pub(super) fn linked_pages(name: &str, bytes: &[u8], path: Option<&str>, o: &Loa
|
||||
let shared = Arc::new(bytes.to_vec());
|
||||
// The file is hashed once for all its pages.
|
||||
let hash = link.hash.clone().unwrap_or_else(|| vectorcraft_doc::links::hash_bytes(bytes));
|
||||
let (mut x, mut warnings, mut cmyk_pages) = (0.0, Vec::<String>::new(), 0);
|
||||
for (i, &index) in picked.iter().enumerate() {
|
||||
let (mut warnings, mut cmyk_pages) = (Vec::<String>::new(), 0);
|
||||
// Each page as read, with its bleed (top, bottom, left, right). The pages are laid out once
|
||||
// the document's bleed is known.
|
||||
let mut read_pages = Vec::with_capacity(picked.len());
|
||||
for &index in &picked {
|
||||
let page = index as u32 + 1;
|
||||
let file_once = document::SharedFile { bytes: &shared, hash: &hash, opened: &opened };
|
||||
// On its trim box, a page shows its bleed box, the artboard on the trim box inside it, so
|
||||
@@ -272,7 +275,7 @@ pub(super) fn linked_pages(name: &str, bytes: &[u8], path: Option<&str>, o: &Loa
|
||||
let page_box = if bleed.is_some() { vectorcraft_doc::PageBox::Bleed } else { document::page_box(crop) };
|
||||
let read = |bounding| document::shared_source(name, file_once, Some(path), page, bounding, page_box, C);
|
||||
// A blank page has no art's bounds: it keeps its crop box, as opening it as art does.
|
||||
let (s, bounding) = match read(bounding) {
|
||||
let (mut s, bounding) = match read(bounding) {
|
||||
Err(e) if bounding && e.to_string().contains("has no art to place") => (read(false)?, false),
|
||||
s => (s?, bounding),
|
||||
};
|
||||
@@ -283,10 +286,26 @@ pub(super) fn linked_pages(name: &str, bytes: &[u8], path: Option<&str>, o: &Loa
|
||||
}
|
||||
cmyk_pages += usize::from(s.color_mode == ColorMode::Cmyk);
|
||||
// The document's bleed is the widest of the pages' on each side.
|
||||
let [top, bottom, left, right] = bleed.unwrap_or_default();
|
||||
for (side, b) in doc.setup.bleed.iter_mut().zip([top, bottom, left, right]) {
|
||||
let sides = bleed.unwrap_or_default();
|
||||
for (side, b) in doc.setup.bleed.iter_mut().zip(sides) {
|
||||
*side = side.max(b.min(vectorcraft_doc::setup::MAX_BLEED));
|
||||
}
|
||||
for w in std::mem::take(&mut s.warnings) {
|
||||
if !warnings.contains(&w) {
|
||||
warnings.push(w);
|
||||
}
|
||||
}
|
||||
read_pages.push((page, s, bounding, sides));
|
||||
}
|
||||
// Each artboard is the gap from the one before plus the bleed on both sides of it: the
|
||||
// document's bleed, which export adds round every artboard, or a page's own bleed box where it
|
||||
// reaches farther. Neither page then shows or exports the other's art.
|
||||
let [_, _, doc_left, doc_right] = doc.setup.bleed;
|
||||
let mut x = 0.0;
|
||||
for (i, (page, s, bounding, [top, bottom, left, right])) in read_pages.into_iter().enumerate() {
|
||||
if i > 0 {
|
||||
x += doc_left.max(left);
|
||||
}
|
||||
let mut node = document::node(&mut doc, &s, LinkInfo { page: Some(page), ..link.clone() }, bounding);
|
||||
if let NodeKind::PlacedDocument(p) = &mut node.kind {
|
||||
p.xf = Affine::translate((x - left, -top));
|
||||
@@ -299,12 +318,7 @@ pub(super) fn linked_pages(name: &str, bytes: &[u8], path: Option<&str>, o: &Loa
|
||||
doc.layers.push(Arc::new(layer));
|
||||
let rect = Rect::new(x, 0.0, x + s.frame.width() - left - right, s.frame.height() - top - bottom);
|
||||
doc.artboards.push(Artboard { id: i as u32 + 1, name: format!("Artboard {}", i + 1), rect, ..board.clone() });
|
||||
x = rect.x1 + gap;
|
||||
for w in s.warnings {
|
||||
if !warnings.contains(&w) {
|
||||
warnings.push(w);
|
||||
}
|
||||
}
|
||||
x = rect.x1 + doc_right.max(right) + gap;
|
||||
}
|
||||
// Pages painted mostly in CMYK read as CMYK documents, as opening them as art does: the
|
||||
// document opens in CMYK (with the CMYK default swatches) when most of its pages do.
|
||||
|
||||
@@ -1205,6 +1205,46 @@ fn link_pages_open_an_ai_file_on_its_trim_box_with_its_bleed() {
|
||||
let _ = std::fs::remove_dir_all(&d);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn link_pages_on_their_trim_boxes_keep_the_bleed_between_the_artboards() {
|
||||
// Two 100 pt trim boxes: the first with 60 pt of bleed on each side, the second with 80 pt on
|
||||
// its left, more than the largest document bleed (72 pt).
|
||||
let entries = format!("/PieceInfo << /Illustrator << /Private << /AIPrivateData1 {} 0 R /NumBlock 1 >> >> >>", first_extra(2));
|
||||
let first = PdfPage {
|
||||
bleed: Some([0.0, 0.0, 220.0, 220.0]),
|
||||
trim: Some([60.0, 60.0, 160.0, 160.0]),
|
||||
entries,
|
||||
..PdfPage::new(220.0, 220.0, "0 g 0 0 220 220 re f")
|
||||
};
|
||||
let second = PdfPage {
|
||||
bleed: Some([0.0, 0.0, 240.0, 220.0]),
|
||||
trim: Some([80.0, 60.0, 180.0, 160.0]),
|
||||
..PdfPage::new(240.0, 220.0, "0 g 0 0 240 220 re f")
|
||||
};
|
||||
let d = std::env::temp_dir().join(format!("vc-ailinkpagesgap-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&d).unwrap();
|
||||
let path = d.join("pages.ai");
|
||||
std::fs::write(&path, pdf_with(&[first, second], &["<< /Length 4 >>\nstream\ndata\nendstream"], None)).unwrap();
|
||||
let path = path.to_string_lossy().to_string();
|
||||
let mut s = Session::new();
|
||||
s.execute("document.open", &json!({"path": path, "linkPages": true})).unwrap();
|
||||
let doc = &s.doc().unwrap().doc;
|
||||
assert_eq!(doc.setup.bleed, [60.0, 60.0, 72.0, 60.0], "top, bottom, left, right");
|
||||
// The first page's bleed ends at 160; the second's starts 36 pt later, 80 pt left of its trim box.
|
||||
let boards: Vec<(f64, f64)> = doc.artboards.iter().map(|a| (a.rect.x0, a.rect.x1)).collect();
|
||||
assert_eq!(boards, [(0.0, 100.0), (276.0, 376.0)]);
|
||||
let shown: Vec<f64> = doc
|
||||
.layers
|
||||
.iter()
|
||||
.map(|l| match &l.children().unwrap()[0].kind {
|
||||
NodeKind::PlacedDocument(p) => p.xf.translation().x,
|
||||
k => panic!("{k:?}"),
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(shown, [-60.0, 196.0], "each page's bleed box round its artboard");
|
||||
let _ = std::fs::remove_dir_all(&d);
|
||||
}
|
||||
|
||||
/// A page of text alone, as text-only art has in its PDF part: no path is painted.
|
||||
const TEXT_ART: &str = "BT /F1 36 Tf 10 40 Td (Text only) Tj ET";
|
||||
|
||||
|
||||
+1
-1
@@ -1282,7 +1282,7 @@ placed document linked to that page of the file, as `file.place` with `link` pla
|
||||
Each page gets an artboard of its `cropTo` box (`bounding`: its art's bounds; a blank page gets its crop box), in a row from the left 36 pt apart, and
|
||||
a layer named after the page (`Page 2`). A PDF-compatible `.ai` with `cropTo: "crop"` gets its trim boxes, as it does
|
||||
when it opens as art. A page on its trim box shows its bleed box round the artboard, and the pages give the document
|
||||
their bleed. The document opens in CMYK when most of those pages are painted mostly in
|
||||
their bleed; the artboards are then 36 pt apart plus the bleed on both sides. The document opens in CMYK when most of those pages are painted mostly in
|
||||
CMYK, unless `colorMode` names a mode. All the pages' objects share one copy of the file. The Links panel lists each
|
||||
page, and `links.embed` makes a page editable art.
|
||||
`document.open` refuses `linkPages` for a file that is not a PDF or a PDF-compatible `.ai`, for a file given as
|
||||
|
||||
Reference in New Issue
Block a user