diff --git a/crates/pdf/src/import.rs b/crates/pdf/src/import.rs index 9dc59f54..7d6745dc 100644 --- a/crates/pdf/src/import.rs +++ b/crates/pdf/src/import.rs @@ -222,6 +222,8 @@ pub fn import_with_report(bytes: &[u8], opts: &ImportOptions) -> Result Result 0.0 { let shift = Affine::translate((dx, 0.0)); for (_, v) in &mut parts { @@ -284,6 +287,13 @@ pub fn import_with_report(bytes: &[u8], opts: &ImportOptions) -> Result= first_id).map(|(_, facts)| facts) { + for ink in &mut facts.ink { + *ink = *ink + kurbo::Vec2::new(dx, 0.0); + } + } ab = Rect::new(ab.x0 + dx, ab.y0, ab.x1 + dx, ab.y1); } art_right = art.x1 + dx; diff --git a/crates/pdf/src/tests_import_lines.rs b/crates/pdf/src/tests_import_lines.rs index 6005e7f0..ea2ea3ad 100644 --- a/crates/pdf/src/tests_import_lines.rs +++ b/crates/pdf/src/tests_import_lines.rs @@ -131,6 +131,28 @@ fn a_stroke_written_as_stroked_glyph_outlines_is_the_types_stroke() { assert_eq!(d.layers[0].children().unwrap().len(), 2); } +/// A `.ai` page moved right in the row, so its art past the artboard clears the page before it +/// (#1528), still has the stroke drawn on its type's glyphs read as the type's stroke. +#[test] +fn a_stroke_on_the_type_of_a_moved_ai_page_is_still_the_types_stroke() { + let ai = "/PieceInfo << /Illustrator << /Private << /AIPrivateData1 7 /NumBlock 1 >> >> >>"; + let content = format!( + "0 g -70 10 80 20 re f BT 1 0 0 rg /F1 24 Tf 10 50 Td (Hi) Tj ET 0 0 1 RG 0.5 w {}{}", + outline('H', 10.0), + outline('i', 10.0 + 0.722 * 24.0) + ); + let pages = [("0 g 10 10 20 20 re f", String::new()), (content.as_str(), HELVETICA.to_string())].map(|(c, resources)| PdfPage { + entries: ai.into(), + resources, + ..PdfPage::new(100.0, 100.0, c) + }); + let d = import(&vectorcraft_testkit::pdf::pdf(&pages, None)).unwrap(); + assert!(d.artboards[1].rect.x0 > d.artboards[0].rect.x1 + 36.0 + 1.0, "page 2 moved: {:?}", d.artboards); + let art = d.layers[1].children().unwrap(); + assert_eq!(art.len(), 2, "the note and the type: {art:?}"); + assert!(matches!(art[1].appearance.items.as_slice(), [AppearanceItem::Stroke(_)]), "{:?}", art[1].appearance); +} + /// A 300 × 200 pt page with `lines` of (x, y from the top, size, text) in Source Sans 3. fn source_sans(lines: &[(f32, f32, f32, &str)]) -> Vec { crate::tests_live_text::text_pdf(lines, false)