reflexo_typst2vec/
utils.rs

1use reflexo::vector::ir::Rgba8Item;
2use typst::layout::Abs;
3use typst::visualize::{Color, Paint};
4
5use super::ir;
6
7/// Additional methods for [`typst::layout::Abs`].
8pub trait AbsExt {
9    /// Convert to a number of points as f32.
10    fn to_f32(self) -> f32;
11}
12
13impl AbsExt for Abs {
14    fn to_f32(self) -> f32 {
15        self.to_pt() as f32
16    }
17}
18
19/// Additional methods for types that can be converted to CSS.
20pub trait ToCssExt {
21    /// Convert to a CSS string.
22    fn to_css(self) -> String;
23}
24
25impl ToCssExt for Rgba8Item {
26    fn to_css(self) -> String {
27        let Rgba8Item { r, g, b, a } = self;
28        if a == 255 {
29            let shorter = format!("#{r:02x}{g:02x}{b:02x}");
30            if shorter.chars().nth(1) == shorter.chars().nth(2)
31                && shorter.chars().nth(3) == shorter.chars().nth(4)
32                && shorter.chars().nth(5) == shorter.chars().nth(6)
33            {
34                return format!(
35                    "#{}{}{}",
36                    shorter.chars().nth(1).unwrap(),
37                    shorter.chars().nth(3).unwrap(),
38                    shorter.chars().nth(5).unwrap()
39                );
40            }
41            return shorter;
42        }
43
44        format!("#{r:02x}{g:02x}{b:02x}{a:02x}")
45    }
46}
47
48impl ToCssExt for Color {
49    fn to_css(self) -> String {
50        let [r, g, b, a] = self.to_rgb().to_vec4_u8();
51        Rgba8Item { r, g, b, a }.to_css()
52    }
53}
54
55impl ToCssExt for Paint {
56    fn to_css(self) -> String {
57        let fill = match self {
58            Paint::Solid(color) => color,
59            // todo: pattern
60            Paint::Tiling(..) => Color::BLACK,
61            // todo: gradient
62            Paint::Gradient(..) => Color::BLACK,
63        };
64        fill.to_css()
65    }
66}
67
68impl ToCssExt for ir::Transform {
69    fn to_css(self) -> String {
70        let regular_scale = self.sx.0 == 1.0 && self.sy.0 == 1.0;
71        let regular_skew = self.kx.0 == 0.0 && self.ky.0 == 0.0;
72        let regular_translate = self.tx.0 == 0.0 && self.ty.0 == 0.0;
73
74        match (regular_scale, regular_skew, regular_translate) {
75            (true, true, true) => String::default(),
76            (true, true, false) => format!(r#"translate({},{})"#, self.tx.0, self.ty.0),
77            (true, false, true) => format!(r#"skew({},{})"#, self.kx.0, self.ky.0),
78            (false, true, true) => format!(r#"scale({},{})"#, self.sx.0, self.sy.0),
79            _ => format!(
80                r#"matrix({},{},{},{},{},{})"#,
81                self.sx.0, self.ky.0, self.kx.0, self.sy.0, self.tx.0, self.ty.0
82            ),
83        }
84    }
85}