diff --git a/Cargo.lock b/Cargo.lock index dcd154367..fd704bd7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -181,9 +181,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" dependencies = [ "serde", ] @@ -214,9 +214,9 @@ checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" [[package]] name = "bytemuck" -version = "1.21.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" dependencies = [ "bytemuck_derive", ] @@ -415,6 +415,15 @@ name = "codex" version = "0.1.1" source = "git+https://github.com/typst/codex?rev=9ac86f9#9ac86f96af5b89fce555e6bba8b6d1ac7b44ef00" +[[package]] +name = "color" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ae467d04a8a8aea5d9a49018a6ade2e4221d92968e8ce55a48c0b1164e5f698" +dependencies = [ + "bytemuck", +] + [[package]] name = "color-print" version = "0.3.7" @@ -964,6 +973,67 @@ dependencies = [ "url", ] +[[package]] +name = "hayro-font" +version = "0.1.0" +dependencies = [ + "log", + "phf", +] + +[[package]] +name = "hayro-interpret" +version = "0.1.0" +dependencies = [ + "bitflags 2.9.1", + "hayro-font", + "hayro-syntax", + "kurbo", + "log", + "peniko", + "phf", + "qcms", + "skrifa", + "smallvec", + "yoke 0.8.0", +] + +[[package]] +name = "hayro-render" +version = "0.1.0" +dependencies = [ + "bytemuck", + "hayro-interpret", + "hayro-syntax", + "image", + "kurbo", + "peniko", + "rustc-hash", + "smallvec", +] + +[[package]] +name = "hayro-syntax" +version = "0.0.1" +dependencies = [ + "flate2", + "kurbo", + "log", + "rustc-hash", + "smallvec", + "zune-jpeg", +] + +[[package]] +name = "hayro-write" +version = "0.1.0" +dependencies = [ + "flate2", + "hayro-syntax", + "log", + "pdf-writer", +] + [[package]] name = "heck" version = "0.5.0" @@ -1271,7 +1341,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "inotify-sys", "libc", ] @@ -1367,7 +1437,6 @@ dependencies = [ [[package]] name = "krilla" version = "0.4.0" -source = "git+https://github.com/LaurenzV/krilla?rev=20c14fe#20c14fefee5002566b3d6668b338bbe2168784e7" dependencies = [ "base64", "bumpalo", @@ -1376,6 +1445,7 @@ dependencies = [ "float-cmp 0.10.0", "fxhash", "gif", + "hayro-write", "image-webp", "imagesize", "once_cell", @@ -1385,6 +1455,7 @@ dependencies = [ "rustybuzz", "siphasher", "skrifa", + "smallvec", "subsetter", "tiny-skia-path", "xmp-writer", @@ -1395,7 +1466,6 @@ dependencies = [ [[package]] name = "krilla-svg" version = "0.1.0" -source = "git+https://github.com/LaurenzV/krilla?rev=20c14fe#20c14fefee5002566b3d6668b338bbe2168784e7" dependencies = [ "flate2", "fontdb", @@ -1408,9 +1478,9 @@ dependencies = [ [[package]] name = "kurbo" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89234b2cc610a7dd927ebde6b41dd1a5d4214cffaef4cf1fb2195d592f92518f" +checksum = "1077d333efea6170d9ccb96d3c3026f300ca0773da4938cc4c811daa6df68b0c" dependencies = [ "arrayvec", "smallvec", @@ -1462,7 +1532,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "libc", "redox_syscall", ] @@ -1628,7 +1698,7 @@ version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "filetime", "fsevent-sys", "inotify", @@ -1710,7 +1780,7 @@ version = "0.10.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "cfg-if", "foreign-types", "libc", @@ -1847,12 +1917,24 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ea27c5015ab81753fc61e49f8cde74999346605ee148bb20008ef3d3150e0dc" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "itoa", "memchr", "ryu", ] +[[package]] +name = "peniko" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f9529efd019889b2a205193c14ffb6e2839b54ed9d2720674f10f4b04d87ac9" +dependencies = [ + "bytemuck", + "color", + "kurbo", + "smallvec", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -2005,7 +2087,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "getopts", "memchr", "unicase", @@ -2118,7 +2200,7 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", ] [[package]] @@ -2221,7 +2303,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "errno", "libc", "linux-raw-sys", @@ -2240,7 +2322,7 @@ version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "bytemuck", "core_maths", "log", @@ -2288,7 +2370,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "core-foundation", "core-foundation-sys", "libc", @@ -2451,9 +2533,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "spin" @@ -3063,7 +3145,7 @@ name = "typst-library" version = "0.13.1" dependencies = [ "az", - "bitflags 2.8.0", + "bitflags 2.9.1", "bumpalo", "chinese-number", "ciborium", @@ -3075,6 +3157,7 @@ dependencies = [ "fontdb", "glidesort", "hayagriva", + "hayro-syntax", "icu_properties", "icu_provider", "icu_provider_blob", @@ -3173,6 +3256,7 @@ version = "0.13.1" dependencies = [ "bytemuck", "comemo", + "hayro-render", "image", "pixglyph", "resvg", @@ -3589,7 +3673,7 @@ version = "0.221.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9845c470a2e10b61dd42c385839cdd6496363ed63b5c9e420b5488b77bd22083" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "indexmap 2.7.1", ] @@ -3724,7 +3808,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 63ea32b94..e868e1650 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,8 @@ fontdb = { version = "0.23", default-features = false } fs_extra = "1.3" glidesort = "0.1.2" hayagriva = "0.8.1" +hayro-syntax = { path = "../hayro/hayro-syntax" } +hayro-render = { path = "../hayro/hayro-render" } heck = "0.5" hypher = "0.1.4" icu_properties = { version = "1.4", features = ["serde"] } @@ -73,8 +75,8 @@ image = { version = "0.25.5", default-features = false, features = ["png", "jpeg indexmap = { version = "2", features = ["serde"] } infer = { version = "0.19.0", default-features = false } kamadak-exif = "0.6" -krilla = { git = "https://github.com/LaurenzV/krilla", rev = "20c14fe", default-features = false, features = ["raster-images", "comemo", "rayon"] } -krilla-svg = { git = "https://github.com/LaurenzV/krilla", rev = "20c14fe" } +krilla = { path = "../krilla/crates/krilla", default-features = false, features = ["raster-images", "comemo", "rayon", "pdf"] } +krilla-svg = { path = "../krilla/crates/krilla-svg" } kurbo = "0.11" libfuzzer-sys = "0.4" lipsum = "0.9" diff --git a/crates/typst-cli/src/args.rs b/crates/typst-cli/src/args.rs index 7459be0f2..093735cbb 100644 --- a/crates/typst-cli/src/args.rs +++ b/crates/typst-cli/src/args.rs @@ -471,6 +471,7 @@ display_possible_values!(DiagnosticFormat); #[derive(Debug, Copy, Clone, Eq, PartialEq, ValueEnum)] pub enum Feature { Html, + PdfEmbedding, } display_possible_values!(Feature); diff --git a/crates/typst-cli/src/world.rs b/crates/typst-cli/src/world.rs index 8ad766b14..ab5216831 100644 --- a/crates/typst-cli/src/world.rs +++ b/crates/typst-cli/src/world.rs @@ -117,6 +117,7 @@ impl SystemWorld { .iter() .map(|&feature| match feature { Feature::Html => typst::Feature::Html, + Feature::PdfEmbedding => typst::Feature::PdfEmbedding, }) .collect(); diff --git a/crates/typst-library/Cargo.toml b/crates/typst-library/Cargo.toml index f4b219882..2297f7ca7 100644 --- a/crates/typst-library/Cargo.toml +++ b/crates/typst-library/Cargo.toml @@ -31,6 +31,7 @@ flate2 = { workspace = true } fontdb = { workspace = true } glidesort = { workspace = true } hayagriva = { workspace = true } +hayro-syntax = { workspace = true } icu_properties = { workspace = true } icu_provider = { workspace = true } icu_provider_blob = { workspace = true } diff --git a/crates/typst-library/src/lib.rs b/crates/typst-library/src/lib.rs index 025e997c6..edbc182fa 100644 --- a/crates/typst-library/src/lib.rs +++ b/crates/typst-library/src/lib.rs @@ -237,6 +237,7 @@ impl FromIterator for Features { #[non_exhaustive] pub enum Feature { Html, + PdfEmbedding, } /// A group of related standard library definitions. diff --git a/crates/typst-library/src/visualize/image/mod.rs b/crates/typst-library/src/visualize/image/mod.rs index f1fa6381b..458787611 100644 --- a/crates/typst-library/src/visualize/image/mod.rs +++ b/crates/typst-library/src/visualize/image/mod.rs @@ -1,5 +1,6 @@ //! Image handling. +mod pdf; mod raster; mod svg; @@ -26,6 +27,7 @@ use crate::layout::{Length, Rel, Sizing}; use crate::loading::{DataSource, Load, LoadSource, Loaded, Readable}; use crate::model::Figurable; use crate::text::{families, LocalName}; +use crate::visualize::image::pdf::{PdfDocument, PdfImage}; /// A raster or vector graphic. /// @@ -126,6 +128,11 @@ pub struct ImageElem { /// A text describing the image. pub alt: Option, + /// The page number that should be embedded as an image. This attribute only has an effect + /// for PDF files. + #[default(1)] + pub page: usize, + /// How the image should adjust itself to a given area (the area is defined /// by the `width` and `height` fields). Note that `fit` doesn't visually /// change anything if the area's aspect ratio is the same as the image's @@ -261,6 +268,15 @@ impl Packed { ) .within(loaded)?, ), + ImageFormat::Vector(VectorFormat::Pdf) => { + let document = PdfDocument::new(loaded.data.clone()).within(loaded)?; + // The user provides the page number staring from 1, further down the pipeline they page + // numbers are 0-based. + let pdf_image = + PdfImage::new(document, self.page.get(styles) - 1).within(loaded)?; + + ImageKind::Pdf(pdf_image) + } }; Ok(Image::new(kind, self.alt.get_cloned(styles), self.scaling.get(styles))) @@ -286,6 +302,7 @@ impl Packed { "jpg" | "jpeg" => return Ok(ExchangeFormat::Jpg.into()), "gif" => return Ok(ExchangeFormat::Gif.into()), "svg" | "svgz" => return Ok(VectorFormat::Svg.into()), + "pdf" => return Ok(VectorFormat::Pdf.into()), "webp" => return Ok(ExchangeFormat::Webp.into()), _ => {} } @@ -373,6 +390,7 @@ impl Image { match &self.0.kind { ImageKind::Raster(raster) => raster.format().into(), ImageKind::Svg(_) => VectorFormat::Svg.into(), + ImageKind::Pdf(_) => VectorFormat::Pdf.into(), } } @@ -381,6 +399,7 @@ impl Image { match &self.0.kind { ImageKind::Raster(raster) => raster.width() as f64, ImageKind::Svg(svg) => svg.width(), + ImageKind::Pdf(pdf) => pdf.width() as f64, } } @@ -389,6 +408,7 @@ impl Image { match &self.0.kind { ImageKind::Raster(raster) => raster.height() as f64, ImageKind::Svg(svg) => svg.height(), + ImageKind::Pdf(pdf) => pdf.height() as f64, } } @@ -397,6 +417,7 @@ impl Image { match &self.0.kind { ImageKind::Raster(raster) => raster.dpi(), ImageKind::Svg(_) => Some(Image::USVG_DEFAULT_DPI), + ImageKind::Pdf(_) => Some(Image::DEFAULT_DPI), } } @@ -435,6 +456,8 @@ pub enum ImageKind { Raster(RasterImage), /// An SVG image. Svg(SvgImage), + /// A PDF image. + Pdf(PdfImage), } impl From for ImageKind { @@ -469,10 +492,20 @@ impl ImageFormat { return Some(Self::Vector(VectorFormat::Svg)); } + if is_pdf(data) { + return Some(Self::Vector(VectorFormat::Pdf)); + } + None } } +/// Checks whether the data looks like a PDF file. +fn is_pdf(data: &[u8]) -> bool { + let head = &data[..data.len().min(2048)]; + memchr::memmem::find(head, b"%PDF-").is_some() +} + /// 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 @@ -493,6 +526,8 @@ fn is_svg(data: &[u8]) -> bool { pub enum VectorFormat { /// The vector graphics format of the web. Svg, + /// The PDF graphics format. + Pdf, } impl From for ImageFormat diff --git a/crates/typst-library/src/visualize/image/pdf.rs b/crates/typst-library/src/visualize/image/pdf.rs new file mode 100644 index 000000000..8cf67469e --- /dev/null +++ b/crates/typst-library/src/visualize/image/pdf.rs @@ -0,0 +1,96 @@ +use crate::diag::LoadResult; +use crate::foundations::Bytes; +use hayro_syntax::pdf::Pdf; +use std::hash::{Hash, Hasher}; +use std::sync::Arc; +use hayro_syntax::document::page::Page; + +#[derive(Clone)] +struct DocumentRepr { + pdf: Arc, + data: Bytes, + page_sizes: Vec<(f32, f32)>, +} + +impl Hash for DocumentRepr { + fn hash(&self, state: &mut H) { + self.data.hash(state); + } +} + +/// A PDF document. +#[derive(Clone, Hash)] +pub struct PdfDocument(Arc); + +impl PdfDocument { + /// Load a PDF document. + #[comemo::memoize] + #[typst_macros::time(name = "load pdf document")] + pub fn new(data: Bytes) -> LoadResult { + // TODO: Remove unwraps + let pdf = Arc::new(Pdf::new(Arc::new(data.clone())).unwrap()); + let pages = pdf.pages().unwrap(); + + let page_sizes = pages.get().iter().map(|p| p.render_dimensions()).collect(); + + Ok(Self(Arc::new(DocumentRepr { data, pdf, page_sizes }))) + } +} + +struct ImageRepr { + pub document: PdfDocument, + pub page_index: usize, + pub width: f32, + pub height: f32, +} + +impl Hash for ImageRepr { + fn hash(&self, state: &mut H) { + self.document.hash(state); + self.page_index.hash(state); + } +} + +/// A page of a PDF file. +#[derive(Clone, Hash)] +pub struct PdfImage(Arc); + +impl PdfImage { + #[comemo::memoize] + pub fn new(document: PdfDocument, page: usize) -> LoadResult { + // TODO: Don't allow loading if pdf-embedding feature is disabled. + // TODO: Remove Unwrap + let dimensions = *(&document.0).page_sizes.get(page).unwrap(); + + Ok(Self(Arc::new(ImageRepr { + document, + page_index: page, + width: dimensions.0, + height: dimensions.1, + }))) + } + + pub fn with_page(&self, f: F) -> R + where + F: FnOnce(&Page) -> R, + { + let pages = self.0.document.0.pdf.pages().unwrap(); + f(&pages.get().get(self.0.page_index).unwrap()) + } + + pub fn width(&self) -> f32 { + self.0.width + } + + pub fn height(&self) -> f32 { + self.0.height + } + + pub fn data(&self) -> &Bytes { + &self.0.document.0.data + } + + pub fn page_index(&self) -> usize { + self.0.page_index + } +} diff --git a/crates/typst-pdf/src/convert.rs b/crates/typst-pdf/src/convert.rs index 9e2aa87b7..a76091e94 100644 --- a/crates/typst-pdf/src/convert.rs +++ b/crates/typst-pdf/src/convert.rs @@ -363,6 +363,11 @@ fn finish( hint: "convert the image to 8 bit instead" ) } + KrillaError::Pdf(_, e, loc) => { + // TODO: Better errors + let span = to_span(loc); + bail!(span, "failed to process PDF"); + } }, } } @@ -576,6 +581,17 @@ fn convert_error( "{prefix} missing document date"; hint: "set the date of the document" ), + ValidationError::DuplicateTagId(_, loc) => error!( + to_span(*loc), + "{prefix} duplicate tag id"; + hint: "please report this as a bug" + ), + ValidationError::UnknownTagId(_, loc) => error!( + to_span(*loc), + "{prefix} unknown tag id"; + hint: "please report this as a bug" + ), + ValidationError::EmbeddedPDF(loc) => error!(to_span(*loc), "TODO"), } } diff --git a/crates/typst-pdf/src/image.rs b/crates/typst-pdf/src/image.rs index 93bdb1950..b6a66ba4d 100644 --- a/crates/typst-pdf/src/image.rs +++ b/crates/typst-pdf/src/image.rs @@ -3,6 +3,7 @@ use std::sync::{Arc, OnceLock}; use image::{DynamicImage, EncodableLayout, GenericImageView, Rgba}; use krilla::image::{BitsPerComponent, CustomImage, ImageColorspace}; +use krilla::pdf::PdfDocument; use krilla::surface::Surface; use krilla_svg::{SurfaceExt, SvgSettings}; use typst_library::diag::{bail, SourceResult}; @@ -60,6 +61,15 @@ pub(crate) fn handle_image( SvgSettings { embed_text: true, ..Default::default() }, ); } + ImageKind::Pdf(pdf) => { + let pdf_data: Arc + Send + Sync> = + Arc::new(pdf.data().clone()); + surface.draw_pdf_page( + &PdfDocument::new(pdf_data.into()).unwrap(), + size.to_krilla(), + pdf.page_index(), + ) + } } if image.alt().is_some() { diff --git a/crates/typst-render/Cargo.toml b/crates/typst-render/Cargo.toml index 7d01d7e38..10bc188c7 100644 --- a/crates/typst-render/Cargo.toml +++ b/crates/typst-render/Cargo.toml @@ -18,6 +18,7 @@ typst-macros = { workspace = true } typst-timing = { workspace = true } bytemuck = { workspace = true } comemo = { workspace = true } +hayro-render = { workspace = true } image = { workspace = true } pixglyph = { workspace = true } resvg = { workspace = true } diff --git a/crates/typst-render/src/image.rs b/crates/typst-render/src/image.rs index 7425bdd2f..52cb84564 100644 --- a/crates/typst-render/src/image.rs +++ b/crates/typst-render/src/image.rs @@ -1,8 +1,9 @@ use std::sync::Arc; - +use hayro_render::{InterpreterSettings, RenderSettings}; use image::imageops::FilterType; use image::{GenericImageView, Rgba}; use tiny_skia as sk; +use tiny_skia::IntSize; use typst_library::foundations::Smart; use typst_library::layout::Size; use typst_library::visualize::{Image, ImageKind, ImageScaling}; @@ -59,9 +60,9 @@ pub fn render_image( /// Prepare a texture for an image at a scaled size. #[comemo::memoize] fn build_texture(image: &Image, w: u32, h: u32) -> Option> { - let mut texture = sk::Pixmap::new(w, h)?; - match image.kind() { + let texture = match image.kind() { ImageKind::Raster(raster) => { + let mut texture = sk::Pixmap::new(w, h)?; let w = texture.width(); let h = texture.height(); @@ -85,15 +86,37 @@ fn build_texture(image: &Image, w: u32, h: u32) -> Option> { let Rgba([r, g, b, a]) = src; *dest = sk::ColorU8::from_rgba(r, g, b, a).premultiply(); } + + texture } ImageKind::Svg(svg) => { + let mut texture = sk::Pixmap::new(w, h)?; let tree = svg.tree(); let ts = tiny_skia::Transform::from_scale( w as f32 / tree.size().width(), h as f32 / tree.size().height(), ); resvg::render(tree, ts, &mut texture.as_mut()); + + texture } - } + ImageKind::Pdf(pdf) => { + let hayro_pix = pdf.with_page(|page| { + // TODO: Configure so that PDF standard fonts can be resolved + let interpreter_settings = InterpreterSettings::default(); + let render_settings = RenderSettings { + x_scale: w as f32 / pdf.width(), + y_scale: h as f32 / pdf.height(), + width: Some(w as u16), + height: Some(h as u16) + }; + hayro_render::render(page, &interpreter_settings, &render_settings) + + }); + + sk::Pixmap::from_vec(hayro_pix.data_as_u8_slice().to_vec(), IntSize::from_wh(w, h)?)? + }, + }; + Some(Arc::new(texture)) } diff --git a/crates/typst-svg/src/image.rs b/crates/typst-svg/src/image.rs index fd4aecd4f..069e5b10a 100644 --- a/crates/typst-svg/src/image.rs +++ b/crates/typst-svg/src/image.rs @@ -66,6 +66,7 @@ pub fn convert_image_to_base64_url(image: &Image) -> EcoString { }), }, ImageKind::Svg(svg) => ("svg+xml", svg.data()), + ImageKind::Pdf(_) => todo!(), }; let mut url = eco_format!("data:image/{format};base64,");