hayro_interpret/
types.rs

1use crate::CacheKey;
2use crate::color::Color;
3use crate::pattern::Pattern;
4use crate::util::hash128;
5use crate::x_object::ImageXObject;
6use kurbo::{BezPath, Cap, Join};
7use smallvec::{SmallVec, smallvec};
8
9/// A clip path.
10#[derive(Debug, Clone)]
11pub struct ClipPath {
12    /// The clipping path.
13    pub path: BezPath,
14    /// The fill rule.
15    pub fill: FillRule,
16}
17
18impl CacheKey for ClipPath {
19    fn cache_key(&self) -> u128 {
20        hash128(&(&self.path.to_svg(), &self.fill))
21    }
22}
23
24/// A stencil image.
25pub struct StencilImage<'a, 'b> {
26    pub(crate) paint: Paint<'a>,
27    pub(crate) image_xobject: ImageXObject<'b>,
28}
29
30impl<'a, 'b> StencilImage<'a, 'b> {
31    /// Perform some operation with the stencil data of the image.
32    pub fn with_stencil(&self, func: impl FnOnce(LumaData, &Paint<'a>)) {
33        if let Some(luma) = self
34            .image_xobject
35            .decoded_object()
36            .and_then(|d| d.luma_data)
37        {
38            func(luma, &self.paint);
39        }
40    }
41}
42
43impl CacheKey for StencilImage<'_, '_> {
44    fn cache_key(&self) -> u128 {
45        self.image_xobject.cache_key()
46    }
47}
48
49/// A raster image.
50pub struct RasterImage<'a>(pub(crate) ImageXObject<'a>);
51
52impl RasterImage<'_> {
53    /// Perform some operation with the RGB and alpha channel of the image.
54    pub fn with_rgba(&self, func: impl FnOnce(RgbData, Option<LumaData>)) {
55        let decoded = self.0.decoded_object();
56
57        if let Some(decoded) = decoded
58            && let Some(rgb) = decoded.rgb_data
59        {
60            func(rgb, decoded.luma_data)
61        }
62    }
63}
64
65impl CacheKey for RasterImage<'_> {
66    fn cache_key(&self) -> u128 {
67        self.0.cache_key()
68    }
69}
70
71/// A type of image.
72pub enum Image<'a, 'b> {
73    /// A stencil image.
74    Stencil(StencilImage<'a, 'b>),
75    /// A normal raster image.
76    Raster(RasterImage<'b>),
77}
78
79impl CacheKey for Image<'_, '_> {
80    fn cache_key(&self) -> u128 {
81        match self {
82            Image::Stencil(i) => i.cache_key(),
83            Image::Raster(i) => i.cache_key(),
84        }
85    }
86}
87
88/// A structure holding 3-channel RGB data.
89#[derive(Clone)]
90pub struct RgbData {
91    /// The actual data. It is guaranteed to have the length width * height * 3.
92    pub data: Vec<u8>,
93    /// The width.
94    pub width: u32,
95    /// The height.
96    pub height: u32,
97    /// Whether the image should be interpolated.
98    pub interpolate: bool,
99}
100
101/// A structure holding 1-channel luma data.
102#[derive(Clone)]
103pub struct LumaData {
104    /// The actual data. It is guaranteed to have the length width * height.
105    pub data: Vec<u8>,
106    /// The width.
107    pub width: u32,
108    /// The height.
109    pub height: u32,
110    /// Whether the image should be interpolated.
111    pub interpolate: bool,
112}
113
114/// A type of paint.
115#[derive(Clone, Debug)]
116pub enum Paint<'a> {
117    /// A solid RGBA color.
118    Color(Color),
119    /// A PDF pattern.
120    Pattern(Box<Pattern<'a>>),
121}
122
123impl CacheKey for Paint<'_> {
124    fn cache_key(&self) -> u128 {
125        match self {
126            Paint::Color(c) => {
127                // TODO: We should actually cache the color with color space etc., not just the
128                // RGBA8 version.
129                hash128(&c.to_rgba().to_rgba8())
130            }
131            Paint::Pattern(p) => p.cache_key(),
132        }
133    }
134}
135
136/// The draw mode that should be used for a path.
137#[derive(Clone, Debug)]
138pub enum PathDrawMode {
139    /// Draw using a fill.
140    Fill(FillRule),
141    /// Draw using a stroke.
142    Stroke(StrokeProps),
143}
144
145/// The draw mode that should be used for a glyph.
146#[derive(Clone, Debug)]
147pub enum GlyphDrawMode {
148    /// Draw using a fill.
149    Fill,
150    /// Draw using a stroke.
151    Stroke(StrokeProps),
152}
153
154/// Stroke properties.
155#[derive(Clone, Debug)]
156pub struct StrokeProps {
157    /// The line width.
158    pub line_width: f32,
159    /// The line cap.
160    pub line_cap: Cap,
161    /// The line join.
162    pub line_join: Join,
163    /// The miter limit.
164    pub miter_limit: f32,
165    /// The dash array.
166    pub dash_array: SmallVec<[f32; 4]>,
167    /// The dash offset.
168    pub dash_offset: f32,
169}
170
171impl Default for StrokeProps {
172    fn default() -> Self {
173        Self {
174            line_width: 1.0,
175            line_cap: Cap::Butt,
176            line_join: Join::Miter,
177            miter_limit: 10.0,
178            dash_array: smallvec![],
179            dash_offset: 0.0,
180        }
181    }
182}
183
184/// A fill rule.
185#[derive(Clone, Debug, Copy, Hash, PartialEq, Eq)]
186pub enum FillRule {
187    /// Non-zero filling.
188    NonZero,
189    /// Even-odd filling.
190    EvenOdd,
191}