From 283fcbb71c5ee73f0bc86a4027197f21b758684a Mon Sep 17 00:00:00 2001 From: PgBiel <9021226+PgBiel@users.noreply.github.com> Date: Thu, 30 Jan 2025 02:36:39 -0300 Subject: [PATCH] attempt 2: use datasource --- .../typst-library/src/visualize/image/mod.rs | 49 ++++++++++++------- .../src/visualize/image/pixmap.rs | 19 ++++++- crates/typst-svg/src/text.rs | 9 ++-- 3 files changed, 55 insertions(+), 22 deletions(-) diff --git a/crates/typst-library/src/visualize/image/mod.rs b/crates/typst-library/src/visualize/image/mod.rs index d268d9e0c..0e62bd616 100644 --- a/crates/typst-library/src/visualize/image/mod.rs +++ b/crates/typst-library/src/visualize/image/mod.rs @@ -17,7 +17,7 @@ use pixmap::{Pixmap, PixmapFormat, PixmapSource}; use typst_syntax::{Span, Spanned}; use typst_utils::LazyHash; -use crate::diag::{bail, At, SourceResult, StrResult}; +use crate::diag::{bail, SourceResult, StrResult}; use crate::engine::Engine; use crate::foundations::{ cast, elem, func, scope, AutoValue, Bytes, Cast, Content, Derived, Dict, NativeElement, @@ -54,11 +54,11 @@ pub struct ImageElem { /// For more details about paths, see the [Paths section]($syntax/#paths). #[required] #[parse( - let source = args.expect::>("source")?; + let source = args.expect::>("source")?; let data = source.load(engine.world)?; Derived::new(source.v, data) )] - pub source: Derived, + pub source: Derived, /// The image's format. Detected automatically by default. /// @@ -124,7 +124,7 @@ impl ImageElem { pub fn decode( span: Span, /// The data to decode as an image. Can be a string for SVGs. - source: ImageSource, + data: Readable, /// The image's format. Detected automatically by default. #[named] format: Option>, @@ -148,7 +148,7 @@ impl ImageElem { scaling: Option, ) -> StrResult { let bytes = data.into_bytes(); - let source = Derived::new(DataSource::Bytes(bytes.clone()), bytes); + let source = Derived::new(ImageSource::DataSource(DataSource::Bytes(bytes.clone())), bytes); let mut elem = ImageElem::new(source); if let Some(format) = format { elem.push_format(format); @@ -240,25 +240,25 @@ impl Image { #[comemo::memoize] #[typst_macros::time(name = "load image")] pub fn new( - source: ImageSource, + data: Derived, format: ImageFormat, options: &ImageOptions, ) -> StrResult { let kind = match format { ImageFormat::Raster(format) => { - let ImageSource::Readable(readable) = source else { - bail!("expected readable source for the given format (str or bytes)"); + let ImageSource::DataSource(_) = data.source else { + bail!("expected non-pixmap source for the given format"); }; - ImageKind::Raster(RasterImage::new(readable.into(), format)?) + ImageKind::Raster(RasterImage::new(data.derived, format)?) } ImageFormat::Vector(VectorFormat::Svg) => { - let ImageSource::Readable(readable) = source else { - bail!("expected readable source for the given format (str or bytes)"); + let ImageSource::DataSource(_) = data.source else { + bail!("expected non-pixmap source for the given format"); }; - ImageKind::Svg(SvgImage::new(readable.into(), options)?) + ImageKind::Svg(SvgImage::new(data.derived, options)?) } ImageFormat::Pixmap(format) => { - let ImageSource::Pixmap(source) = source else { + let ImageSource::Pixmap(source) = data.source else { bail!("source must be a pixmap"); }; ImageKind::Pixmap(Pixmap::new(source, format)?) @@ -336,22 +336,37 @@ impl Debug for Image { } } -/// Information required to decode an image. +/// Information specifying the source of an image's byte data. #[derive(Debug, Clone, PartialEq, Hash)] pub enum ImageSource { - Readable(Readable), + DataSource(DataSource), Pixmap(Arc), } impl From for ImageSource { fn from(bytes: Bytes) -> Self { - ImageSource::Readable(Readable::Bytes(bytes)) + ImageSource::DataSource(DataSource::Bytes(bytes)) + } +} + +impl Load for Spanned { + type Output = Bytes; + + fn load(&self, world: Tracked) -> SourceResult { + match &self.v { + ImageSource::DataSource(data_source) => Spanned::new(data_source, self.span).load(world), + ImageSource::Pixmap(pixmap_source) => Ok(pixmap_source.data.clone()), + } } } cast! { ImageSource, - data: Readable => ImageSource::Readable(data), + self => match self { + Self::DataSource(data) => data.into_value(), + Self::Pixmap(pixmap) => pixmap.into_value(), + }, + data: DataSource => ImageSource::DataSource(data), mut dict: Dict => { let source = ImageSource::Pixmap(Arc::new(PixmapSource { data: dict.take("data")?.cast()?, diff --git a/crates/typst-library/src/visualize/image/pixmap.rs b/crates/typst-library/src/visualize/image/pixmap.rs index cc0358f87..895d908ce 100644 --- a/crates/typst-library/src/visualize/image/pixmap.rs +++ b/crates/typst-library/src/visualize/image/pixmap.rs @@ -3,9 +3,9 @@ use std::sync::Arc; use image::{DynamicImage, ImageBuffer, Pixel}; use crate::diag::{bail, StrResult}; -use crate::foundations::{Bytes, Cast}; +use crate::foundations::{cast, dict, Bytes, Cast, Dict}; -#[derive(Debug, PartialEq, Hash)] +#[derive(Debug, Clone, PartialEq, Hash)] pub struct PixmapSource { pub data: Bytes, pub pixel_width: u32, @@ -13,6 +13,21 @@ pub struct PixmapSource { pub icc_profile: Option, } +cast! { + Arc, + self => dict!("data" => self.data.clone(), "pixel_width" => self.pixel_width, "pixel_height" => self.pixel_height, "icc_profile" => self.icc_profile.clone()).into_value(), + mut dict: Dict => { + let source = Arc::new(PixmapSource { + data: dict.take("data")?.cast()?, + pixel_width: dict.take("pixel-width")?.cast()?, + pixel_height: dict.take("pixel-height")?.cast()?, + icc_profile: dict.take("icc-profile").ok().map(|value| value.cast()).transpose()?, + }); + dict.finish(&["data", "pixel-width", "pixel-height", "icc-profile"])?; + source + } +} + /// A raster image based on a flat pixmap. #[derive(Clone, Hash)] pub struct Pixmap(Arc); diff --git a/crates/typst-svg/src/text.rs b/crates/typst-svg/src/text.rs index 36bd4c729..36e67a161 100644 --- a/crates/typst-svg/src/text.rs +++ b/crates/typst-svg/src/text.rs @@ -244,9 +244,12 @@ fn convert_bitmap_glyph_to_image(font: &Font, id: GlyphId) -> Option<(Image, f64 if raster.format != ttf_parser::RasterImageFormat::PNG { return None; } - let image = - Image::new(Bytes::new(raster.data.to_vec()).into(), RasterFormat::Png.into(), &Default::default(),) - .ok()?; + let image = Image::new( + Bytes::new(raster.data.to_vec()).into(), + RasterFormat::Png.into(), + &Default::default(), + ) + .ok()?; Some((image, raster.x as f64, raster.y as f64)) }