Export: EPS, legacy .ai, EMF/WMF and DXF give one note for images that can't be decoded

EPS, EMF, WMF and DXF exports gave each image they left out because it
couldn't be decoded its own warning, "image '<key>' could not be
decoded and was left out", which names the internal key the document
stores the image under. A version 7 .ai said "an image that can't be
decoded or is too large was left out".

The four writers now give the note raster exports, PDF and the legacy
.ai flattening give, "an image couldn't be decoded and is missing from
the picture", once per export. In a version 7 .ai it is one line with
the note for flattened art. The other image notes in the same
functions no longer name the key: EPS's note for an image too large to
write, and DXF's notes for an image with no pixels (its rows in 23
catalogs are reworded) and one that could not be written. Legacy .ai
gives a separate note for an image that is empty or too large.

Docs: docs/mcp.md (EPS, DXF export, EMF and WMF, aiVersion "7").
This commit is contained in:
dotCooCoo
2026-10-22 06:13:32 +07:00
committed by bflatastic
parent 3bb0f07a4b
commit 4e4723699d
34 changed files with 158 additions and 40 deletions
+18
View File
@@ -125,6 +125,24 @@ fn placed_images_come_back_as_linked_files() {
let _ = std::fs::remove_dir_all(dir);
}
/// Two placed images whose pixel data can't be decoded are left out of the drawing and get no
/// linked file, and `warnings` holds the note raster exports give, once, without naming either
/// image's key.
#[test]
fn images_that_cant_be_decoded_give_the_raster_note_once() {
const NOTE: &str = "an image couldn't be decoded and is missing from the picture";
let mut s = session(200.0, 100.0, 1);
crate::tests_menucmds::place_undecodable_png(&mut s);
crate::tests_menucmds::place_undecodable_png_sized(&mut s, 32, 16);
let keys: Vec<String> = s.doc().unwrap().doc.images.keys().cloned().collect();
assert_eq!(keys.len(), 2);
let r = s.execute("document.export", &json!({"format": "dxf"})).unwrap();
let w: Vec<&str> = r["warnings"].as_array().unwrap().iter().filter_map(Value::as_str).collect();
assert_eq!(w.iter().filter(|w| **w == NOTE).count(), 1, "{w:?}");
assert!(!w.iter().any(|w| keys.iter().any(|k| w.contains(k.as_str()))), "{w:?}");
assert!(entities(&text(&r)).is_empty() && r.get("linked").is_none(), "{r}");
}
#[test]
fn bad_dxf_options_are_refused() {
let mut s = two_boards();
+17
View File
@@ -156,6 +156,23 @@ fn placed_images_are_written_and_previews_are_black_and_white_on_request() {
assert!(l3.contains("/FlateDecode filter >> image"));
}
/// Two placed images whose pixel data can't be decoded are left out of the EPS, and `warnings`
/// holds the note raster exports give, once, without naming either image's key.
#[test]
fn images_that_cant_be_decoded_give_the_raster_note_once() {
const NOTE: &str = "an image couldn't be decoded and is missing from the picture";
let mut s = session(200.0, 100.0, 1);
crate::tests_menucmds::place_undecodable_png(&mut s);
crate::tests_menucmds::place_undecodable_png_sized(&mut s, 32, 16);
let keys: Vec<String> = s.doc().unwrap().doc.images.keys().cloned().collect();
assert_eq!(keys.len(), 2);
let r = s.execute("document.exportEps", &json!({"previewFormat": "none"})).unwrap();
let w = warnings(&r);
assert_eq!(w.iter().filter(|w| *w == NOTE).count(), 1, "{w:?}");
assert!(!w.iter().any(|w| keys.iter().any(|k| w.contains(k.as_str()))), "{w:?}");
assert!(!postscript(&b64(&r)).contains("filter >> image"), "no image is written");
}
#[test]
fn bad_eps_options_are_refused_and_formats_list_eps() {
let mut s = session(100.0, 100.0, 1);
@@ -95,6 +95,24 @@ fn raster_effects_are_written_as_images() {
assert!(kinds.contains(&114), "the shadow is an image with transparency");
}
/// Two placed images whose pixel data can't be decoded are left out of an EMF or WMF, and
/// `warnings` holds the note raster exports give, once, without naming either image's key.
#[test]
fn images_that_cant_be_decoded_give_the_raster_note_once() {
const NOTE: &str = "an image couldn't be decoded and is missing from the picture";
let mut s = session(200.0, 100.0, 1);
crate::tests_menucmds::place_undecodable_png(&mut s);
crate::tests_menucmds::place_undecodable_png_sized(&mut s, 32, 16);
let keys: Vec<String> = s.doc().unwrap().doc.images.keys().cloned().collect();
assert_eq!(keys.len(), 2);
for format in ["emf", "wmf"] {
let r = s.execute("document.export", &json!({"format": format})).unwrap();
let w: Vec<&str> = r["warnings"].as_array().unwrap().iter().filter_map(Value::as_str).collect();
assert_eq!(w.iter().filter(|w| **w == NOTE).count(), 1, "{format}: {w:?}");
assert!(!w.iter().any(|w| keys.iter().any(|k| w.contains(k.as_str()))), "{format}: {w:?}");
}
}
#[test]
fn metafiles_open_and_place() {
let mut s = two_boards();