Merge pull request #854 from rschuerer/fix/ai-non-native-art
Fix #861: open .ai files whose non-native art has ASCII85 lines starting with %_
This commit is contained in:
commit
ef574b6319
|
|
@ -311,6 +311,9 @@ const SKIPPED: &[(&str, &str)] = &[
|
|||
("Alternate_Content", "End_Versioned_Content"),
|
||||
];
|
||||
|
||||
/// The note for a `/ForeignObject`, art the editor shows but doesn't edit.
|
||||
pub const NON_NATIVE_ART: &str = "non-native art (a placed PDF's content) is left out: VectorCraft doesn't draw it from the editing data yet";
|
||||
|
||||
/// A section comment's marker without its `AI<version>_` prefix and value (`AI14_BeginSymbol` →
|
||||
/// `BeginSymbol`); DSC comments (`%%BeginProlog`) keep their `%`.
|
||||
fn marker(c: &str) -> &str {
|
||||
|
|
@ -645,8 +648,13 @@ impl<'a> Reader<'a> {
|
|||
"," => {
|
||||
if let Some(Frame { kind: Kind::Obj(o), base, .. }) = self.frames.last_mut() {
|
||||
obj::add_entry(o, &mut self.stack, *base);
|
||||
// Binary data in ASCII85 follows, up to its `~>`.
|
||||
if o.ty == "Binary" && o.entries.last().is_some_and(|(k, _)| k.as_deref() == Some("ASCII85Decode")) {
|
||||
// Binary data in ASCII85 follows, up to its `~>`: a `/Binary` dictionary's
|
||||
// (`/ASCII85Decode ,`) or a non-native art object's (`/ForeignObject`'s
|
||||
// `/Data ,`, the PDF it keeps), in comment lines. ASCII85 has `_`, so a line
|
||||
// of it may start with `%_` and read as hidden tokens: a `(` there would open
|
||||
// a string that swallows the rest of the layer.
|
||||
let key = o.entries.last().and_then(|(k, _)| k.as_deref());
|
||||
if (o.ty == "Binary" && key == Some("ASCII85Decode")) || (o.ty == "ForeignObject" && key == Some("Data")) {
|
||||
self.lex.skip_past(b"~>");
|
||||
}
|
||||
}
|
||||
|
|
@ -826,6 +834,9 @@ impl<'a> Reader<'a> {
|
|||
"Document" => self.document(&o),
|
||||
"AI11Text" => self.text_slot(&o)?,
|
||||
"SymbolInstance" => self.unreadable("symbols"),
|
||||
// Art Illustrator shows but doesn't edit (a placed PDF's content): its PDF is kept in
|
||||
// the dictionary, which nothing draws from yet, so the file opens without it.
|
||||
"ForeignObject" => self.warn(NON_NATIVE_ART),
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -329,6 +329,18 @@ fn sections_it_skips() {
|
|||
assert_eq!(art(&doc).len(), 1);
|
||||
}
|
||||
|
||||
/// Non-native art (a placed PDF's content) keeps its PDF as ASCII85 in comment lines after
|
||||
/// `/Data ,`. ASCII85 has `_`, so a line may start with `%_`, which otherwise reads as hidden
|
||||
/// tokens, and a `(` in it would swallow the rest of the layer (a letterhead saved by Illustrator
|
||||
/// 28 wouldn't open: "it ends inside a layer"). The art is left out with a note.
|
||||
#[test]
|
||||
fn non_native_art_is_skipped_with_its_ascii85_data() {
|
||||
let foreign = "/ForeignObject :\n1 /Version ,\n2 0 0 2 10 20 /RTransform ,\n/Data ,\n%,u@!!/MSk8%41#ocdN=10d&\n%_O%*mGn(RduU.]4`[u[.f\n%_;(]<[%\n%1H@<P2`V<S,pbuU7L]\\~>\n;\n0 0 Xd\n6 () XW\n0 Ae\n";
|
||||
let s = read_ok(&layer(&format!("{foreign}{}", rect_path(0.0, 0.0, 1.0, 1.0) + "f\n")));
|
||||
assert_eq!(art(&s.doc).len(), 1);
|
||||
assert!(s.warnings.iter().any(|w| w == read::NON_NATIVE_ART), "{:?}", s.warnings);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cmyk_documents() {
|
||||
let doc = read_ok(&format!("%AI9_ColorModel: 2\n{}", layer(""))).doc;
|
||||
|
|
|
|||
|
|
@ -450,7 +450,8 @@ CMYK too.
|
|||
PostScript files (`.eps`, and `.ai` files saved in older formats or without PDF compatibility) open through the EPS
|
||||
reader (see EPS and PostScript import). An `.ai` saved without PDF compatibility (its PDF part is only a placeholder
|
||||
page) opens from its editing data alone: its type is made from the file's text document where it can be (point type), and
|
||||
what can't be is left out with a warning; without editing data it says it can't be opened.
|
||||
what can't be is left out with a warning; so is non-native art (the content of a placed PDF, which Illustrator shows but
|
||||
doesn't edit and keeps as a PDF inside the editing data); without editing data it says it can't be opened.
|
||||
|
||||
What a PDF holds comes in as editable art: soft masks become opacity masks (an alpha mask as a white copy of its art;
|
||||
the backdrop colour gives Clip, an inverting transfer function Invert), transparency groups keep isolation and knockout,
|
||||
|
|
|
|||
Loading…
Reference in New Issue