diff --git a/Cargo.lock b/Cargo.lock index e3634c4a6..8313e25a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1181,12 +1181,12 @@ source = "git+https://github.com/storytold/craft-libs?rev=19692b6190465671e41967 [[package]] name = "craft-eps" version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551#8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551" +source = "git+https://github.com/storytold/craft-libs?rev=ba24fe2435adb3c81ad6057faf36365fbba736cf#ba24fe2435adb3c81ad6057faf36365fbba736cf" [[package]] name = "craft-eps" version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=ba24fe2435adb3c81ad6057faf36365fbba736cf#ba24fe2435adb3c81ad6057faf36365fbba736cf" +source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558" [[package]] name = "craft-epub" @@ -1201,12 +1201,12 @@ dependencies = [ [[package]] name = "craft-file-formats" version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551#8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551" +source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558" dependencies = [ - "craft-eps 0.1.0 (git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551)", - "craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551)", - "craft-svg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551)", - "craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551)", + "craft-eps 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)", + "craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)", + "craft-svg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)", + "craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)", "serde", "serde_json", ] @@ -1242,10 +1242,10 @@ dependencies = [ [[package]] name = "craft-idml" version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551#8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551" +source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558" dependencies = [ - "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551)", - "craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551)", + "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)", + "craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)", "thiserror 2.0.21", ] @@ -1303,6 +1303,28 @@ dependencies = [ "zune-jpegxl", ] +[[package]] +name = "craft-image-codecs" +version = "0.1.0" +source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558" +dependencies = [ + "craft-jpeg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)", + "exr", + "flate2", + "half", + "image", + "image-webp", + "jpeg-encoder", + "png", + "rayon", + "serde_json", + "thiserror 2.0.21", + "tiff", + "zune-core", + "zune-jpeg", + "zune-jpegxl", +] + [[package]] name = "craft-indd" version = "0.1.0" @@ -1327,6 +1349,14 @@ dependencies = [ "thiserror 2.0.21", ] +[[package]] +name = "craft-jpeg" +version = "0.1.0" +source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558" +dependencies = [ + "thiserror 2.0.21", +] + [[package]] name = "craft-keymap" version = "0.1.0" @@ -1493,18 +1523,6 @@ dependencies = [ "usvg 0.48.1", ] -[[package]] -name = "craft-svg" -version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551#8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551" -dependencies = [ - "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551)", - "flate2", - "kurbo", - "roxmltree 0.21.2", - "thiserror 2.0.21", -] - [[package]] name = "craft-svg" version = "0.1.0" @@ -1520,6 +1538,19 @@ dependencies = [ "usvg 0.48.1", ] +[[package]] +name = "craft-svg" +version = "0.1.0" +source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558" +dependencies = [ + "craft-image-codecs 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)", + "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)", + "flate2", + "kurbo", + "roxmltree 0.21.2", + "thiserror 2.0.21", +] + [[package]] name = "craft-ui" version = "0.1.0" @@ -1649,6 +1680,15 @@ dependencies = [ "thiserror 2.0.21", ] +[[package]] +name = "craft-xml" +version = "0.1.0" +source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558" +dependencies = [ + "quick-xml 0.41.0", + "thiserror 2.0.21", +] + [[package]] name = "craft-xml" version = "0.1.0" @@ -1707,6 +1747,16 @@ dependencies = [ "zip 9.1.1", ] +[[package]] +name = "craft-zip" +version = "0.1.0" +source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558" +dependencies = [ + "flate2", + "thiserror 2.0.21", + "zip 9.1.1", +] + [[package]] name = "craft-zip" version = "0.1.0" @@ -2052,6 +2102,7 @@ dependencies = [ name = "designcraft-idml" version = "0.20.1" dependencies = [ + "craft-file-formats", "craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=fbdd905cdddd2f0de930021a3f92bcf1684973be)", "craft-svg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=cc23ffd4d26f3074808e2187d332564817624f8f)", "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=fbdd905cdddd2f0de930021a3f92bcf1684973be)", diff --git a/Cargo.toml b/Cargo.toml index c17950ebf..fb77f1d6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ craft-wordmodel = { git = "https://github.com/storytold/craft-libs", rev = "ba24 craft-csv = { git = "https://github.com/dylanmtaylor/craft-libs", rev = "44d7ac8d942dbd87048f82b3efc3e0d14483cc8d", version = "=0.1.0" } craft-image-codecs = { git = "https://github.com/dylanmtaylor/craft-libs", rev = "2e670cf9377b523112f3fe4b409399772c745895", version = "=0.1.0" } craft-psd = { git = "https://github.com/dylanmtaylor/craft-libs", rev = "2e670cf9377b523112f3fe4b409399772c745895", version = "=0.1.0" } -craft-file-formats = { git = "https://github.com/storytold/craft-libs", rev = "8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551", version = "=0.1.0" } +craft-file-formats = { git = "https://github.com/storytold/craft-libs", rev = "eed3c28cf016723d004d6f2c79c61424c15d4558", version = "=0.1.0" } craft-opc = { git = "https://github.com/storytold/craft-libs", rev = "8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551", version = "=0.1.0" } craft-pptx = { git = "https://github.com/storytold/craft-libs", rev = "f6cab1980", version = "=0.1.0" } # Shared keyboard bindings: chords, overrides, conflicts, egui dispatch, the Keyboard Shortcuts dialog. diff --git a/crates/idml/Cargo.toml b/crates/idml/Cargo.toml index 7a6a64058..d6bfd451b 100644 --- a/crates/idml/Cargo.toml +++ b/crates/idml/Cargo.toml @@ -16,6 +16,7 @@ designcraft-images = { workspace = true } craft-idml = { workspace = true } craft-xml = { workspace = true } craft-svg = { workspace = true } +craft-file-formats = { workspace = true } thiserror = { workspace = true } log = { workspace = true } diff --git a/crates/idml/src/lib.rs b/crates/idml/src/lib.rs index 82f956363..673ecab2b 100644 --- a/crates/idml/src/lib.rs +++ b/crates/idml/src/lib.rs @@ -79,44 +79,37 @@ pub enum IdmlError { pub type Result = std::result::Result; -/// Sniff an image's MIME type and pixel size (PNG, JPEG, GIF, WebP, TIFF, PDF, EPS). +/// MIME and size metadata for a placed image, delegated to the shared format registry and image +/// boundary. The application keeps only its EPS proxy pixel-size policy. pub(crate) fn sniff_image(b: &[u8]) -> (Option<&'static str>, Option<(u32, u32)>) { - if designcraft_images::is_eps(b) { - return (Some("application/postscript"), designcraft_images::eps_pixel_size(b)); - } - let be32 = |i: usize| b.get(i..i + 4).map(|s| u32::from_be_bytes([s[0], s[1], s[2], s[3]])); - if b.starts_with(b"\x89PNG\r\n\x1a\n") { - return (Some("image/png"), be32(16).zip(be32(20))); - } - if b.starts_with(&[0xFF, 0xD8]) { - let mut i = 2; - while i + 9 < b.len() { - if b[i] != 0xFF { - i += 1; - continue; - } - let m = b[i + 1]; - let len = u16::from_be_bytes([b[i + 2], b[i + 3]]) as usize; - if matches!(m, 0xC0..=0xC3 | 0xC5..=0xC7 | 0xC9..=0xCB | 0xCD..=0xCF) { - let h = u16::from_be_bytes([b[i + 5], b[i + 6]]) as u32; - let w = u16::from_be_bytes([b[i + 7], b[i + 8]]) as u32; - return (Some("image/jpeg"), Some((w, h))); - } - i += 2 + len; - } - return (Some("image/jpeg"), None); - } - if b.starts_with(b"GIF8") && b.len() >= 10 { - return (Some("image/gif"), Some((u16::from_le_bytes([b[6], b[7]]) as u32, u16::from_le_bytes([b[8], b[9]]) as u32))); - } - if b.starts_with(b"RIFF") && b.get(8..12) == Some(b"WEBP") { - return (Some("image/webp"), None); - } - if b.starts_with(b"II*\0") || b.starts_with(b"MM\0*") { - return (Some("image/tiff"), None); - } - if b.starts_with(b"%PDF") { - return (Some("application/pdf"), None); - } - (None, None) + let Some(format) = craft_file_formats::detect("", b) else { return (None, None) }; + let mime = format.mime_type(); + let pixels = match format { + craft_file_formats::Format::Eps => designcraft_images::eps_pixel_size(b), + craft_file_formats::Format::Png + | craft_file_formats::Format::Jpeg + | craft_file_formats::Format::Bmp + | craft_file_formats::Format::Gif + | craft_file_formats::Format::Tiff + | craft_file_formats::Format::WebP + | craft_file_formats::Format::Tga + | craft_file_formats::Format::Ico + | craft_file_formats::Format::Pnm + | craft_file_formats::Format::Pcx + | craft_file_formats::Format::Xpm + | craft_file_formats::Format::Dds + | craft_file_formats::Format::Qoi + | craft_file_formats::Format::OpenExr + | craft_file_formats::Format::Hdr + | craft_file_formats::Format::Avif + | craft_file_formats::Format::Fits + | craft_file_formats::Format::Dpx + | craft_file_formats::Format::Jxl + | craft_file_formats::Format::Cineon + | craft_file_formats::Format::Dicom + | craft_file_formats::Format::Iff + | craft_file_formats::Format::Psd => designcraft_images::pixel_size(b), + _ => None, + }; + (mime, pixels) }