zeno/
style.rs

1//! Path styles.
2
3/// Describes the visual style of a fill.
4#[derive(Copy, Clone, PartialEq, Eq, Debug)]
5pub enum Fill {
6    /// The non-zero fill rule.
7    NonZero,
8    /// The even-odd fill rule.
9    EvenOdd,
10}
11
12/// Defines the connection between two segments of a stroke.
13#[derive(Copy, Clone, PartialEq, Eq, Debug)]
14pub enum Join {
15    /// A straight line connecting the segments.
16    Bevel,
17    /// The segments are extended to their natural intersection point.
18    Miter,
19    /// An arc between the segments.
20    Round,
21}
22
23/// Defines the shape to be drawn at the beginning or end of a stroke.
24#[derive(Copy, Clone, PartialEq, Eq, Debug)]
25pub enum Cap {
26    /// Flat cap.
27    Butt,
28    /// Square cap with dimensions equal to half the stroke width.
29    Square,
30    /// Rounded cap with radius equal to half the stroke width.
31    Round,
32}
33
34/// Describes the visual style of a stroke.
35#[derive(Copy, Clone, Debug)]
36pub struct Stroke<'a> {
37    /// Width of the stroke.
38    pub width: f32,
39    /// Style for connecting segments of the stroke.
40    pub join: Join,
41    /// Limit for miter joins.
42    pub miter_limit: f32,
43    /// Style for capping the beginning of an open subpath.
44    pub start_cap: Cap,
45    /// Style for capping the end of an open subpath.
46    pub end_cap: Cap,
47    /// Lengths of dashes in alternating on/off order.
48    pub dashes: &'a [f32],
49    /// Offset of the first dash.
50    pub offset: f32,
51    /// True if the stroke width should be affected by the scale of a transform.
52    pub scale: bool,
53}
54
55impl Default for Stroke<'_> {
56    fn default() -> Self {
57        Self {
58            width: 1.,
59            join: Join::Miter,
60            miter_limit: 4.,
61            start_cap: Cap::Butt,
62            end_cap: Cap::Butt,
63            dashes: &[],
64            offset: 0.,
65            scale: true,
66        }
67    }
68}
69
70impl<'a> Stroke<'a> {
71    /// Creates a new stroke style with the specified width.
72    #[allow(clippy::field_reassign_with_default)]
73    pub fn new(width: f32) -> Self {
74        let mut s = Self::default();
75        s.width = width;
76        s
77    }
78
79    /// Sets the width of the stroke. The default is 1.
80    pub fn width(&mut self, width: f32) -> &mut Self {
81        self.width = width;
82        self
83    }
84
85    /// Sets the join style that determines how individual segments of the path
86    /// will be connected. The default is miter.
87    pub fn join(&mut self, join: Join) -> &mut Self {
88        self.join = join;
89        self
90    }
91
92    /// Sets the limit for miter joins beyond which a bevel will be generated.
93    /// The default is 4.
94    pub fn miter_limit(&mut self, limit: f32) -> &mut Self {
95        self.miter_limit = limit;
96        self
97    }
98
99    /// Sets the cap style that will be generated at the start and end of the
100    /// stroke. Note that this will override the individual start and end cap
101    /// options. The default is butt.
102    pub fn cap(&mut self, cap: Cap) -> &mut Self {
103        self.start_cap = cap;
104        self.end_cap = cap;
105        self
106    }
107
108    /// Sets both the start and end cap styles for the stroke.
109    pub fn caps(&mut self, start: Cap, end: Cap) -> &mut Self {
110        self.start_cap = start;
111        self.end_cap = end;
112        self
113    }
114
115    /// Sets the dash array and offset of the stroke. The default is an empty
116    /// array, meaning that the stroke will be drawn as a continuous line.
117    pub fn dash(&mut self, dashes: &'a [f32], offset: f32) -> &mut Self {
118        self.dashes = dashes;
119        self.offset = offset;
120        self
121    }
122
123    /// Sets whether or not scaling is applied to the stroke. The default is true.
124    pub fn scale(&mut self, scale: bool) -> &mut Self {
125        self.scale = scale;
126        self
127    }
128}
129
130/// Represents the style of a path for rendering or hit testing.
131#[derive(Copy, Clone, Debug)]
132pub enum Style<'a> {
133    Fill(Fill),
134    Stroke(Stroke<'a>),
135}
136
137impl Default for Style<'_> {
138    fn default() -> Self {
139        Self::Fill(Fill::NonZero)
140    }
141}
142
143impl Style<'_> {
144    /// Returns true if the style is a stroke.
145    pub fn is_stroke(&self) -> bool {
146        matches!(self, Self::Stroke(_))
147    }
148}
149
150impl From<Fill> for Style<'_> {
151    fn from(style: Fill) -> Self {
152        Self::Fill(style)
153    }
154}
155
156impl<'a> From<Stroke<'a>> for Style<'a> {
157    fn from(style: Stroke<'a>) -> Self {
158        Self::Stroke(style)
159    }
160}
161
162impl<'a> From<&'a Stroke<'a>> for Style<'a> {
163    fn from(style: &'a Stroke<'a>) -> Self {
164        Self::Stroke(*style)
165    }
166}
167
168impl<'a> From<&'a mut Stroke<'a>> for Style<'a> {
169    fn from(style: &'a mut Stroke<'a>) -> Self {
170        Self::Stroke(*style)
171    }
172}