diff --git a/Cargo.lock b/Cargo.lock index ab2d2cc83..4b70e06bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1259,6 +1259,12 @@ dependencies = [ "serde", ] +[[package]] +name = "infer" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" + [[package]] name = "inotify" version = "0.11.0" @@ -3127,6 +3133,7 @@ dependencies = [ "comemo", "ecow", "image", + "infer", "krilla", "krilla-svg", "serde", diff --git a/Cargo.toml b/Cargo.toml index 12870b809..bc563b980 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,6 +71,7 @@ icu_segmenter = { version = "1.4", features = ["serde"] } if_chain = "1" image = { version = "0.25.5", default-features = false, features = ["png", "jpeg", "gif"] } indexmap = { version = "2", features = ["serde"] } +infer = { version = "0.19.0", default-features = false } kamadak-exif = "0.6" krilla = { version = "0.4.0", default-features = false, features = ["raster-images", "comemo", "rayon"] } krilla-svg = "0.1.0" diff --git a/crates/typst-pdf/Cargo.toml b/crates/typst-pdf/Cargo.toml index f6f08b5bc..5745d0530 100644 --- a/crates/typst-pdf/Cargo.toml +++ b/crates/typst-pdf/Cargo.toml @@ -23,6 +23,7 @@ bytemuck = { workspace = true } comemo = { workspace = true } ecow = { workspace = true } image = { workspace = true } +infer = { workspace = true } krilla = { workspace = true } krilla-svg = { workspace = true } serde = { workspace = true } diff --git a/crates/typst-pdf/src/embed.rs b/crates/typst-pdf/src/embed.rs index 6ed65a2b6..f0cd9060a 100644 --- a/crates/typst-pdf/src/embed.rs +++ b/crates/typst-pdf/src/embed.rs @@ -34,6 +34,8 @@ pub(crate) fn embed_files( }, }; let data: Arc + Send + Sync> = Arc::new(embed.data.clone()); + // TODO: update when new krilla version lands (https://github.com/LaurenzV/krilla/pull/203) + let compress = should_compress(&embed.data).unwrap_or(true); let file = EmbeddedFile { path, @@ -41,7 +43,7 @@ pub(crate) fn embed_files( description, association_kind, data: data.into(), - compress: true, + compress, location: Some(span.into_raw().get()), }; @@ -52,3 +54,69 @@ pub(crate) fn embed_files( Ok(()) } + +fn should_compress(data: &[u8]) -> Option { + let ty = infer::get(data)?; + match ty.matcher_type() { + infer::MatcherType::App => None, + infer::MatcherType::Archive => match ty.mime_type() { + #[rustfmt::skip] + "application/zip" + | "application/vnd.rar" + | "application/gzip" + | "application/x-bzip2" + | "application/vnd.bzip3" + | "application/x-7z-compressed" + | "application/x-xz" + | "application/vnd.ms-cab-compressed" + | "application/vnd.debian.binary-package" + | "application/x-compress" + | "application/x-lzip" + | "application/x-rpm" + | "application/zstd" + | "application/x-lz4" + | "application/x-ole-storage" => Some(false), + _ => None, + }, + infer::MatcherType::Audio => match ty.mime_type() { + #[rustfmt::skip] + "audio/mpeg" + | "audio/m4a" + | "audio/opus" + | "audio/ogg" + | "audio/x-flac" + | "audio/amr" + | "audio/aac" + | "audio/x-ape" => Some(false), + _ => None, + }, + infer::MatcherType::Book => None, + infer::MatcherType::Doc => None, + infer::MatcherType::Font => None, + infer::MatcherType::Image => match ty.mime_type() { + #[rustfmt::skip] + "image/jpeg" + | "image/jp2" + | "image/png" + | "image/webp" + | "image/vnd.ms-photo" + | "image/heif" + | "image/avif" + | "image/jxl" + | "image/vnd.djvu" => None, + _ => None, + }, + infer::MatcherType::Text => None, + infer::MatcherType::Video => match ty.mime_type() { + #[rustfmt::skip] + "video/mp4" + | "video/x-m4v" + | "video/x-matroska" + | "video/webm" + | "video/quicktime" + | "video/x-flv" => Some(false), + _ => None, + }, + infer::MatcherType::Custom => None, + } +}