Export: legacy .ai gives the size note for an image with empty data

An image whose data is empty failed to decode before the size check, so a
version 7 .ai said it couldn't be decoded. The writer now checks for empty
data first and gives "an image that is empty or too large for legacy .ai
was left out". docs/mcp.md now says the DXF decode note applies to R13 and
later; R12 leaves out every image with its own note.
This commit is contained in:
dotCooCoo
2026-10-22 06:13:32 +07:00
committed by bflatastic
parent 4e4723699d
commit e66bca39b2
3 changed files with 31 additions and 3 deletions
+6 -1
View File
@@ -1305,7 +1305,12 @@ impl<'a> Writer<'a> {
if !invertible(m) {
return;
}
let Some(img) = self.doc.images.get(&im.key).and_then(|b| image::load_from_memory(&b.bytes).ok()) else {
let blob = self.doc.images.get(&im.key);
if blob.is_some_and(|b| b.bytes.is_empty()) {
self.warn(LARGE_IMAGE);
return;
}
let Some(img) = blob.and_then(|b| image::load_from_memory(&b.bytes).ok()) else {
self.warn(UNDECODED);
return;
};
+22
View File
@@ -382,6 +382,28 @@ fn images_are_written_in_the_form_the_specification_shows() {
assert!(rgb.iter().zip([247.0, 148.0, 29.0]).all(|(c, want)| (c * 255.0 - want).abs() < 0.1), "{rgb:?}");
}
/// An image whose data is empty is left out with the note for empty or too large images, and an
/// image whose data can't be decoded is left out with the decode note.
#[test]
fn empty_images_get_the_size_note_and_undecodable_ones_the_decode_note() {
let notes = |bytes: Vec<u8>| {
let mut doc = Document::new(100.0, 100.0);
doc.layers.clear();
let layer = doc.add_layer(Some("Images"));
let blob = ImageBlob::new("image/png", bytes);
let key = blob.content_key();
doc.images.insert(key.clone(), blob);
let im = ImageObject { key, width: 4, height: 2, xf: Affine::IDENTITY, link: None, placement: Default::default() };
let node = Node::new(doc.alloc_id(), NodeKind::Image(Box::new(im)));
doc.insert(Some(layer), usize::MAX, node).unwrap();
let out = export_legacy_ai(&doc, &LegacyAiOptions::default()).unwrap();
assert!(rasters(&String::from_utf8(out.bytes).unwrap()).is_empty());
out.warnings
};
assert_eq!(notes(vec![]), [LARGE_IMAGE]);
assert_eq!(notes(b"not an image".to_vec()), [UNDECODED]);
}
#[test]
fn a_gradient_fill_and_its_stroke_are_one_object() {
let mut doc = Document::new(100.0, 100.0);
+3 -2
View File
@@ -3207,8 +3207,9 @@ width profiles, arrowheads) as filled outlines; `"editability"` keeps type as te
`alterPaths` writes every stroke as its filled outline, `outlineText` outlines type, `selectedOnly` writes only the
selected objects in their layers (every export takes it), and `useArtboards: true` writes one drawing per chosen
artboard holding the art over it. What DXF can't hold (gradients and patterns as one colour, blending, opacity masks,
raster effects, clipping) comes back in `warnings`. An image that can't be decoded is left out with no linked file,
and `warnings` carries "an image couldn't be decoded and is missing from the picture" once for all such images.
raster effects, clipping) comes back in `warnings`. In R13 and later, an image that can't be decoded is left out with
no linked file, and `warnings` carries "an image couldn't be decoded and is missing from the picture" once for all such
images.
DWG can't be written (no openly licensed writer exists): `document.formats` lists it under `unsupported` with that
hint, and exporting to it answers with the hint to export DXF. PICT files are not supported either and say so when