mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-31 13:17:19 -06:00
Merge pull request #4658 from mockydevs/fix/ai-page-cropped-to-art
.ai import: a PDF part cropped to the art no longer hides the layers
This commit is contained in:
@@ -535,6 +535,27 @@ fn an_ai_file_whose_pdf_part_is_only_text_still_opens_from_editing_data_that_rea
|
||||
check_sample(&s);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_ai_file_whose_pdf_part_is_cropped_to_its_art_opens_from_its_layers() {
|
||||
// A 400 × 200 pt artboard with two red bars across (100, 50)–(300, 150). The PDF part's page
|
||||
// is that art's box, 200 × 100 pt (the editing data's bounding box), not the artboard.
|
||||
let red = "0 1 1 0 1 0 0 Xa\n";
|
||||
let art = ai::layer("Art", &format!("{red}{}f\n{red}{}f\n", ai::rect(100.0, 50.0, 180.0, 150.0), ai::rect(220.0, 50.0, 300.0, 150.0)));
|
||||
let data = ai::editing_data_in([100.0, 50.0, 300.0, 150.0], [0.0, 0.0, 400.0, 200.0], &art);
|
||||
let page = "1 0 0 rg 0 0 80 100 re f 120 0 80 100 re f";
|
||||
let mut s = Session::new();
|
||||
let r = open(&mut s, "cropped.ai", &ai::ai(&compressed(data.as_bytes()), page), json!({})).unwrap();
|
||||
assert!(!r["warnings"].to_string().contains("weren't read"), "{r}");
|
||||
let doc = &s.doc().unwrap().doc;
|
||||
assert_eq!(names(&doc.layers), ["Art"]);
|
||||
assert_eq!(doc.artboards.len(), 1);
|
||||
assert_eq!(doc.artboards[0].rect, vectorcraft_geom::Rect::new(0.0, 0.0, 400.0, 200.0), "the file's artboard, not its page");
|
||||
let bars = doc.layers[0].children().unwrap();
|
||||
assert_eq!(bars.len(), 2);
|
||||
let b = bars[0].geometric_bounds().unwrap();
|
||||
assert!((b.x0 - 100.0).abs() < 0.01 && (b.y0 - 50.0).abs() < 0.01, "where the artboard has it: {b:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn editing_data_false_opens_only_what_the_page_prints() {
|
||||
let mut s = Session::new();
|
||||
|
||||
@@ -79,8 +79,18 @@ pub(super) fn build_from(
|
||||
let page_rect = visible.artboards.first().map(|a| a.rect).ok_or("it has no page")?;
|
||||
// The layers' art in the document's terms: a Large Canvas editing copy is written at 1/N
|
||||
// scale, which `to_doc` carries, so its art and the page reach the same size (#2031).
|
||||
let rect = to_doc.transform_rect_bbox(art_box);
|
||||
if (rect.width() - page_rect.width()).abs() > 0.5 || (rect.height() - page_rect.height()).abs() > 0.5 {
|
||||
let fits = |r: &Rect| (r.width() - page_rect.width()).abs() <= 0.5 && (r.height() - page_rect.height()).abs() <= 0.5;
|
||||
let mut rect = to_doc.transform_rect_bbox(art_box);
|
||||
// A `.ai` whose PDF part's pages are cropped to its art (each page the box of all of it,
|
||||
// the editing data's bounding box) rather than to its artboards: the layers are compared
|
||||
// with the page on that box, and keep their artboards.
|
||||
if matches!(page, Page::Artboard)
|
||||
&& !fits(&rect)
|
||||
&& let Some(art) = bbox.map(|[a, b, c, d]| to_doc.transform_rect_bbox(Rect::new(a, b, c, d))).filter(fits)
|
||||
{
|
||||
rect = art;
|
||||
}
|
||||
if !fits(&rect) {
|
||||
// Both sizes in points as the fields show them, and the editing data's page to the
|
||||
// file's as a scale (1:10 is a tenth of its size) when its sides are in proportion and
|
||||
// the scale doesn't round to 1:1.
|
||||
|
||||
@@ -381,11 +381,18 @@ fn an_ai_file_that_cant_be_read_through_its_editing_data_keeps_its_pdf_part() {
|
||||
let (d, w, read) = crate::layered_ai(b"nothing", pdf.clone(), vec![], false, false, 1.0);
|
||||
assert_eq!(d.layers.len(), pdf.layers.len());
|
||||
assert!(w.is_empty() && !read);
|
||||
// Editing data that isn't for this page.
|
||||
let other = native(&layer("Jig", true, &square(10, 10))).replace("%AI3_Cropmarks: 0 0 100 100", "%AI3_Cropmarks: 0 0 50 50");
|
||||
// Editing data that isn't for this page: neither its artboard nor its art's box is the page.
|
||||
let other = native(&layer("Jig", true, &square(10, 10))).replace(" 0 0 100 100", " 0 0 50 50");
|
||||
let (d, w, _) = crate::layered_ai(&private(&other), pdf.clone(), vec![], false, false, 1.0);
|
||||
assert_eq!(names(&d), names(&pdf));
|
||||
assert!(w.iter().any(|w| w.contains("for a 50 × 50 pt page, the file's 100 × 100 pt page at 1:2")), "{w:?}");
|
||||
// A page cropped to the art's box, not the artboard, is that art's page: the layers are read,
|
||||
// with their artboard.
|
||||
let cropped = native(&layer("Jig", true, &square(10, 10))).replace("%AI3_Cropmarks: 0 0 100 100", "%AI3_Cropmarks: 0 0 50 50");
|
||||
let (d, w, read) = crate::layered_ai(&private(&cropped), pdf.clone(), vec![], false, false, 1.0);
|
||||
assert!(read, "{w:?}");
|
||||
assert_eq!(names(&d), ["Jig"]);
|
||||
assert_eq!(d.artboards[0].rect.size(), vectorcraft_geom::Size::new(50.0, 50.0));
|
||||
}
|
||||
|
||||
/// #2034: editing data for a page of another size gives both sizes in points, in an EPS's note and
|
||||
|
||||
@@ -5,9 +5,17 @@
|
||||
/// Editing data of a `width` × `height` page: header comments (the art's bounding box and the crop
|
||||
/// marks are the page), `body` (setup and layers), the trailer.
|
||||
pub fn editing_data(width: f64, height: f64, body: &str) -> String {
|
||||
editing_data_in([0.0, 0.0, width, height], [0.0, 0.0, width, height], body)
|
||||
}
|
||||
|
||||
/// [`editing_data`] whose art's bounding box (`x0 y0 x1 y1`, art space) is `art` and whose
|
||||
/// artboard (the crop marks) is `board`.
|
||||
pub fn editing_data_in(art: [f64; 4], board: [f64; 4], body: &str) -> String {
|
||||
let [a0, a1, a2, a3] = art;
|
||||
let [b0, b1, b2, b3] = board;
|
||||
format!(
|
||||
"{PS_HEADER}\n%%Creator: VectorCraft tests\n%%BoundingBox: 0 0 {width} {height}\n%%HiResBoundingBox: 0 0 {width} {height}\n\
|
||||
%AI5_FileFormat 14.0\n%AI3_Cropmarks: 0 0 {width} {height}\n%%EndComments\n\
|
||||
"{PS_HEADER}\n%%Creator: VectorCraft tests\n%%BoundingBox: {a0} {a1} {a2} {a3}\n%%HiResBoundingBox: {a0} {a1} {a2} {a3}\n\
|
||||
%AI5_FileFormat 14.0\n%AI3_Cropmarks: {b0} {b1} {b2} {b3}\n%%EndComments\n\
|
||||
%%BeginProlog\n%%EndProlog\n%%BeginSetup\n%%EndSetup\n{body}\n%%PageTrailer\ngsave annotatepage grestore showpage\n%%Trailer\n%%EOF\n"
|
||||
)
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user