diff options
| author | Laurenz <laurmaedje@gmail.com> | 2025-02-17 11:56:00 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-17 10:56:00 +0000 |
| commit | 25c86accbb4adc0e7542d2c5957dff6e939cbf48 (patch) | |
| tree | 8db19e48038ffe1eeee1232dc54ec242ce48e029 /crates/typst-library/src/visualize | |
| parent | 5fc679f3e7501ee5831f1b4b7789350f43b4c221 (diff) | |
More robust SVG auto-detection (#5878)
Diffstat (limited to 'crates/typst-library/src/visualize')
| -rw-r--r-- | crates/typst-library/src/visualize/image/mod.rs | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/crates/typst-library/src/visualize/image/mod.rs b/crates/typst-library/src/visualize/image/mod.rs index 97189e22..258eb96f 100644 --- a/crates/typst-library/src/visualize/image/mod.rs +++ b/crates/typst-library/src/visualize/image/mod.rs @@ -398,8 +398,7 @@ impl ImageFormat { return Some(Self::Raster(RasterFormat::Exchange(format))); } - // SVG or compressed SVG. - if data.starts_with(b"<svg") || data.starts_with(&[0x1f, 0x8b]) { + if is_svg(data) { return Some(Self::Vector(VectorFormat::Svg)); } @@ -407,6 +406,21 @@ impl ImageFormat { } } +/// Checks whether the data looks like an SVG or a compressed SVG. +fn is_svg(data: &[u8]) -> bool { + // Check for the gzip magic bytes. This check is perhaps a bit too + // permissive as other formats than SVGZ could use gzip. + if data.starts_with(&[0x1f, 0x8b]) { + return true; + } + + // If the first 2048 bytes contain the SVG namespace declaration, we assume + // that it's an SVG. Note that, if the SVG does not contain a namespace + // declaration, usvg will reject it. + let head = &data[..data.len().min(2048)]; + memchr::memmem::find(head, b"http://www.w3.org/2000/svg").is_some() +} + /// A vector graphics format. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)] pub enum VectorFormat { |
