1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//! Path styles.

/// Describes the visual style of a fill.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Fill {
    /// The non-zero fill rule.
    NonZero,
    /// The even-odd fill rule.
    EvenOdd,
}

/// Defines the connection between two segments of a stroke.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Join {
    /// A straight line connecting the segments.
    Bevel,
    /// The segments are extended to their natural intersection point.
    Miter,
    /// An arc between the segments.
    Round,
}

/// Defines the shape to be drawn at the beginning or end of a stroke.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Cap {
    /// Flat cap.
    Butt,
    /// Square cap with dimensions equal to half the stroke width.
    Square,
    /// Rounded cap with radius equal to half the stroke width.
    Round,
}

/// Describes the visual style of a stroke.
#[derive(Copy, Clone, Debug)]
pub struct Stroke<'a> {
    /// Width of the stroke.
    pub width: f32,
    /// Style for connecting segments of the stroke.
    pub join: Join,
    /// Limit for miter joins.
    pub miter_limit: f32,
    /// Style for capping the beginning of an open subpath.
    pub start_cap: Cap,
    /// Style for capping the end of an open subpath.
    pub end_cap: Cap,
    /// Lengths of dashes in alternating on/off order.
    pub dashes: &'a [f32],
    /// Offset of the first dash.
    pub offset: f32,
    /// True if the stroke width should be affected by the scale of a transform.
    pub scale: bool,
}

impl Default for Stroke<'_> {
    fn default() -> Self {
        Self {
            width: 1.,
            join: Join::Miter,
            miter_limit: 4.,
            start_cap: Cap::Butt,
            end_cap: Cap::Butt,
            dashes: &[],
            offset: 0.,
            scale: true,
        }
    }
}

impl<'a> Stroke<'a> {
    /// Creates a new stroke style with the specified width.
    pub fn new(width: f32) -> Self {
        let mut s = Self::default();
        s.width = width;
        s
    }

    /// Sets the width of the stroke. The default is 1.
    pub fn width(&mut self, width: f32) -> &mut Self {
        self.width = width;
        self
    }

    /// Sets the join style that determines how individual segments of the path
    /// will be connected. The default is miter.
    pub fn join(&mut self, join: Join) -> &mut Self {
        self.join = join;
        self
    }

    /// Sets the limit for miter joins beyond which a bevel will be generated.
    /// The default is 4.
    pub fn miter_limit(&mut self, limit: f32) -> &mut Self {
        self.miter_limit = limit;
        self
    }

    /// Sets the cap style that will be generated at the start and end of the
    /// stroke. Note that this will override the individual start and end cap
    /// options. The default is butt.
    pub fn cap(&mut self, cap: Cap) -> &mut Self {
        self.start_cap = cap;
        self.end_cap = cap;
        self
    }

    /// Sets both the start and end cap styles for the stroke.
    pub fn caps(&mut self, start: Cap, end: Cap) -> &mut Self {
        self.start_cap = start;
        self.end_cap = end;
        self
    }

    /// Sets the dash array and offset of the stroke. The default is an empty
    /// array, meaning that the stroke will be drawn as a continuous line.
    pub fn dash(&mut self, dashes: &'a [f32], offset: f32) -> &mut Self {
        self.dashes = dashes;
        self.offset = offset;
        self
    }

    /// Sets whether or not scaling is applied to the stroke. The default is true.
    pub fn scale(&mut self, scale: bool) -> &mut Self {
        self.scale = scale;
        self
    }
}

/// Represents the style of a path for rendering or hit testing.
#[derive(Copy, Clone, Debug)]
pub enum Style<'a> {
    Fill(Fill),
    Stroke(Stroke<'a>),
}

impl Default for Style<'_> {
    fn default() -> Self {
        Self::Fill(Fill::NonZero)
    }
}

impl Style<'_> {
    /// Returns true if the style is a stroke.
    pub fn is_stroke(&self) -> bool {
        match self {
            Self::Stroke(_) => true,
            _ => false,
        }
    }
}

impl From<Fill> for Style<'_> {
    fn from(style: Fill) -> Self {
        Self::Fill(style)
    }
}

impl<'a> From<Stroke<'a>> for Style<'a> {
    fn from(style: Stroke<'a>) -> Self {
        Self::Stroke(style)
    }
}

impl<'a> From<&'a Stroke<'a>> for Style<'a> {
    fn from(style: &'a Stroke<'a>) -> Self {
        Self::Stroke(*style)
    }
}

impl<'a> From<&'a mut Stroke<'a>> for Style<'a> {
    fn from(style: &'a mut Stroke<'a>) -> Self {
        Self::Stroke(*style)
    }
}