.ai import: a page's art past its artboard no longer lies over the page before it
A PDF-compatible .ai keeps its art past the artboard edge unclipped (#646), and its pages are laid out in a row 36 pt apart. Art that a page draws far to the left of its artboard (notes beside a design, say) then lay over the page before it. There it was taken for that page's art: the check against the editing data found art its layers don't have and opened the file as its PDF part, without the art outside its artboards, and place_pages left that art behind when it moved the pages. Such a page now moves right until its art clears the art before it. Plain PDFs (clipped to the page) keep the 36 pt gap.
This commit is contained in:
parent
9dfa7bf931
commit
ba68fcfbfc
|
|
@ -197,6 +197,8 @@ pub fn import_with_report(bytes: &[u8], opts: &ImportOptions) -> Result<ImportRe
|
|||
b.colors.uncalibrated_rgb = opts.uncalibrated_rgb && picked.iter().filter_map(|&n| pages.get(n)).any(crate::pages::has_private_data);
|
||||
let cache = InterpreterCache::new();
|
||||
let mut x = 0.0;
|
||||
// Where the next page's art may begin (a `.ai` page's art reaches past its artboard).
|
||||
let mut clear = f64::NEG_INFINITY;
|
||||
// Every page only text over private data: a file saved without its PDF part shows a notice
|
||||
// there, not its art. A page that states where its art is isn't that notice.
|
||||
let (mut only_text, mut art_boxes) = (true, false);
|
||||
|
|
@ -267,6 +269,25 @@ pub fn import_with_report(bytes: &[u8], opts: &ImportOptions) -> Result<ImportRe
|
|||
if clipped {
|
||||
b.warn(PAST_PAGE_NOTE);
|
||||
}
|
||||
// A `.ai` page keeps its art past the artboard edge, unclipped (#646), so a page whose art
|
||||
// reaches far to the left would lay it over the page before it in the row: there it would
|
||||
// be taken for that page's art (by the check against the editing data, which then finds
|
||||
// art its layers don't have there, and by `place_pages`). Such a page moves right until its
|
||||
// art clears the art before it.
|
||||
let mut art_right = f64::NEG_INFINITY;
|
||||
if ai && let Some(art) = parts.iter().flat_map(|(_, v)| v.iter()).filter_map(|n| n.visual_bounds()).reduce(|a, b| a.union(b)) {
|
||||
let dx = (clear - art.x0).max(0.0);
|
||||
if dx > 0.0 {
|
||||
let shift = Affine::translate((dx, 0.0));
|
||||
for (_, v) in &mut parts {
|
||||
for n in v.iter_mut() {
|
||||
Arc::make_mut(n).transform(shift, false);
|
||||
}
|
||||
}
|
||||
ab = Rect::new(ab.x0 + dx, ab.y0, ab.x1 + dx, ab.y1);
|
||||
}
|
||||
art_right = art.x1 + dx;
|
||||
}
|
||||
let children: Vec<Arc<Node>> = parts.iter().flat_map(|(_, v)| v.iter().cloned()).collect();
|
||||
only_text &= ai && is_only_text(&children);
|
||||
art_boxes |= crate::pages::states_art(page);
|
||||
|
|
@ -278,6 +299,7 @@ pub fn import_with_report(bytes: &[u8], opts: &ImportOptions) -> Result<ImportRe
|
|||
ab = art;
|
||||
}
|
||||
x = right + opts.artboard_gap;
|
||||
clear = right.max(art_right) + opts.artboard_gap;
|
||||
doc.artboards.push(Artboard {
|
||||
id: i as u32 + 1,
|
||||
name: format!("Artboard {}", i + 1),
|
||||
|
|
|
|||
|
|
@ -158,6 +158,27 @@ fn art_of_neighbouring_artboards_off_a_page_is_left_to_its_own_page() {
|
|||
assert_eq!(d.layers[0].children().map_or(0, |c| c.len()), 2);
|
||||
}
|
||||
|
||||
/// A `.ai` keeps its art past the artboard edge (#646): a note mostly left of artboard 2 (as notes
|
||||
/// for a design are put beside it) doesn't lie over artboard 1 in the row, where it would be taken
|
||||
/// for that page's art: page 2 moves right until its art clears page 1's.
|
||||
#[test]
|
||||
fn art_of_an_ai_page_reaching_left_does_not_lie_over_the_page_before() {
|
||||
let ai = "/PieceInfo << /Illustrator << /Private << /AIPrivateData1 7 /NumBlock 1 >> >> >>";
|
||||
let page = |content: &str| PdfPage { entries: ai.into(), ..PdfPage::new(100.0, 100.0, content) };
|
||||
// Page 2's note runs from 70 points left of its box to 10 points into it.
|
||||
let pages = [page("0 g 10 10 20 20 re f"), page("1 1 1 rg 1 0 0 RG -70 10 80 60 re B")];
|
||||
let d = open(&pdf(&pages, None), ImportOptions::default());
|
||||
let (a, b) = (d.artboards[0].rect, d.artboards[1].rect);
|
||||
let note = d.layers[1].children().unwrap()[0].visual_bounds().unwrap();
|
||||
assert!(note.x0 >= a.x1 + 36.0, "the note clears artboard 1: {note:?} {a:?}");
|
||||
assert!((b.x0 - note.x0 - 70.0).abs() < 1.0, "and keeps its place by artboard 2: {note:?} {b:?}");
|
||||
assert_eq!((b.width(), b.height()), (100.0, 100.0));
|
||||
// A plain PDF clips its art to the page: its pages stay 36 points apart.
|
||||
let plain = [PdfPage::new(100.0, 100.0, "0 g 10 10 20 20 re f"), PdfPage::new(100.0, 100.0, "1 0 0 RG -70 10 80 60 re S")];
|
||||
let d = open(&pdf(&plain, None), ImportOptions::default());
|
||||
assert_eq!(d.artboards[1].rect.x0, d.artboards[0].rect.x1 + 36.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_encrypted_pdf_opens_with_its_password_only() {
|
||||
let bytes = pdf(&[PdfPage::new(200.0, 100.0, "1 0 0 rg 10 10 50 50 re f")], Some("secret"));
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue