reflexo_typst2vec/
convert.rs

1pub use reflexo::vector::ir::*;
2
3use reflexo::hash::{item_hash128, Fingerprint};
4use typst::layout::{
5    Abs as TypstAbs, Angle as TypstAngle, Axes as TypstAxes, Point as TypstPoint,
6    Ratio as TypstRatio, Transform as TypstTransform,
7};
8use typst::text::Font;
9use typst::utils::Scalar as TypstScalar;
10use typst::visualize::{ImageFormat, RasterFormat, VectorFormat};
11
12use crate::hash::typst_affinite_hash;
13use crate::{FromTypst, IntoTypst, TryFromTypst};
14
15impl FromTypst<Rgba8Item> for typst::visualize::Color {
16    fn from_typst(v: Rgba8Item) -> Self {
17        typst::visualize::Color::from_u8(v.r, v.g, v.b, v.a)
18    }
19}
20
21impl FromTypst<typst::visualize::ColorSpace> for ColorSpace {
22    fn from_typst(value: typst::visualize::ColorSpace) -> Self {
23        use typst::visualize::ColorSpace::*;
24        match value {
25            Oklab => Self::Oklab,
26            Oklch => Self::Oklch,
27            Srgb => Self::Srgb,
28            D65Gray => Self::D65Gray,
29            LinearRgb => Self::LinearRgb,
30            Hsl => Self::Hsl,
31            Hsv => Self::Hsv,
32            Cmyk => Self::Cmyk,
33        }
34    }
35}
36
37impl TryFromTypst<ColorSpace> for typst::visualize::ColorSpace {
38    type Error = ();
39
40    fn try_from_typst(value: ColorSpace) -> Result<Self, ()> {
41        use typst::visualize::ColorSpace::*;
42        Ok(match value {
43            ColorSpace::Luma => return Err(()),
44            ColorSpace::Oklab => Oklab,
45            ColorSpace::Oklch => Oklch,
46            ColorSpace::Srgb => Srgb,
47            ColorSpace::D65Gray => D65Gray,
48            ColorSpace::LinearRgb => LinearRgb,
49            ColorSpace::Hsl => Hsl,
50            ColorSpace::Hsv => Hsv,
51            ColorSpace::Cmyk => Cmyk,
52        })
53    }
54}
55
56impl FromTypst<TypstScalar> for Scalar {
57    fn from_typst(scalar: TypstScalar) -> Self {
58        Self(scalar.get() as f32)
59    }
60}
61
62impl FromTypst<Scalar> for TypstScalar {
63    fn from_typst(scalar: Scalar) -> Self {
64        <TypstScalar as std::convert::From<f64>>::from(scalar.0 as f64)
65    }
66}
67
68impl FromTypst<TypstRatio> for Scalar {
69    fn from_typst(ratio: TypstRatio) -> Self {
70        Self(ratio.get() as f32)
71    }
72}
73
74impl FromTypst<TypstAbs> for Scalar {
75    fn from_typst(ratio: TypstAbs) -> Self {
76        Self(ratio.to_pt() as f32)
77    }
78}
79
80impl FromTypst<TypstAngle> for Scalar {
81    fn from_typst(scalar: TypstAngle) -> Self {
82        Self(scalar.to_rad() as f32)
83    }
84}
85
86impl<U, T> FromTypst<TypstAxes<U>> for Axes<T>
87where
88    U: IntoTypst<T>,
89{
90    fn from_typst(typst_axes: TypstAxes<U>) -> Self {
91        Self {
92            x: typst_axes.x.into_typst(),
93            y: typst_axes.y.into_typst(),
94        }
95    }
96}
97
98impl<T, U> FromTypst<Axes<T>> for TypstAxes<U>
99where
100    T: IntoTypst<U>,
101{
102    fn from_typst(axes: Axes<T>) -> Self {
103        Self {
104            x: axes.x.into_typst(),
105            y: axes.y.into_typst(),
106        }
107    }
108}
109
110impl FromTypst<TypstPoint> for Point {
111    fn from_typst(p: TypstPoint) -> Self {
112        Self {
113            x: p.x.into_typst(),
114            y: p.y.into_typst(),
115        }
116    }
117}
118
119impl FromTypst<TypstTransform> for Transform {
120    fn from_typst(typst_transform: TypstTransform) -> Self {
121        Self {
122            sx: typst_transform.sx.into_typst(),
123            ky: typst_transform.ky.into_typst(),
124            kx: typst_transform.kx.into_typst(),
125            sy: typst_transform.sy.into_typst(),
126            tx: typst_transform.tx.into_typst(),
127            ty: typst_transform.ty.into_typst(),
128        }
129    }
130}
131
132impl FromTypst<Font> for FontItem {
133    fn from_typst(font: Font) -> Self {
134        let hash = reflexo::hash::hash32(&font);
135        let fingerprint = Fingerprint::from_u128(item_hash128(&font));
136
137        let metrics = font.metrics();
138        Self {
139            fingerprint,
140            hash,
141            family: font.info().family.clone().into(),
142            cap_height: Scalar(metrics.cap_height.get() as f32),
143            ascender: Scalar(metrics.ascender.get() as f32),
144            descender: Scalar(metrics.descender.get() as f32),
145            units_per_em: Scalar(font.units_per_em() as f32),
146            vertical: false, // todo: check vertical
147            glyphs: Vec::new(),
148            glyph_cov: bitvec::vec::BitVec::new(),
149        }
150    }
151}
152
153/// Collect image data from [`typst::visualize::Image`].
154impl FromTypst<typst::visualize::Image> for Image {
155    fn from_typst(image: typst::visualize::Image) -> Self {
156        let format = match image.format() {
157            ImageFormat::Raster(e) => match e {
158                RasterFormat::Jpg => "jpeg",
159                RasterFormat::Png => "png",
160                RasterFormat::Gif => "gif",
161            },
162            ImageFormat::Vector(e) => match e {
163                VectorFormat::Svg => "svg+xml",
164            },
165        };
166
167        // steal prehash from [`typst::image::Image`]
168        let hash = typst_affinite_hash(&image);
169
170        Image {
171            data: image.data().to_vec(),
172            format: format.into(),
173            size: Axes::new(image.width() as u32, image.height() as u32),
174            alt: image.alt().map(|s| s.into()),
175            hash: Fingerprint::from_u128(hash),
176        }
177    }
178}