ailloli_ui_core/style/
stroke.rs

1//! Stroke style primitives shared by renderable line-like commands.
2
3use crate::style::Color;
4
5/// Line ending style.
6///
7/// Possible values are butt, square, and round caps.
8///
9/// # Examples
10///
11/// ```
12/// use ailloli_ui_core::LineCap;
13/// assert_ne!(LineCap::Butt, LineCap::Round);
14/// ```
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum LineCap {
17    /// Ends exactly at each endpoint.
18    Butt,
19    /// Extends by half the stroke width with a square end.
20    Square,
21    /// Extends with a semicircular end.
22    Round,
23}
24
25/// Line join style.
26///
27/// Possible values are miter, bevel, and round joins.
28///
29/// # Examples
30///
31/// ```
32/// use ailloli_ui_core::LineJoin;
33/// assert_ne!(LineJoin::Miter, LineJoin::Bevel);
34/// ```
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum LineJoin {
37    /// Extends outer edges until they meet, bounded by `miter_limit`.
38    Miter,
39    /// Cuts the outer corner with a straight segment.
40    Bevel,
41    /// Connects segments with a circular arc.
42    Round,
43}
44
45/// Stroke styling for polylines and future path primitives.
46///
47/// # Examples
48///
49/// ```
50/// use ailloli_ui_core::{Color, StrokeStyle};
51/// let stroke = StrokeStyle::new(2.0, Color::WHITE);
52/// assert_eq!(stroke.width, 2.0);
53/// ```
54#[derive(Debug, Clone, Copy, PartialEq)]
55pub struct StrokeStyle {
56    /// Linear-RGBA stroke color.
57    pub color: Color,
58    /// Requested width in logical pixels.
59    pub width: f32,
60    /// Endpoint shape for open paths.
61    pub cap: LineCap,
62    /// Shape joining adjacent path segments.
63    pub join: LineJoin,
64    /// Miter-length ratio limit used only with [`LineJoin::Miter`].
65    pub miter_limit: f32,
66}
67
68impl StrokeStyle {
69    /// Creates a stroke with caller width/color and the remaining defaults.
70    ///
71    /// Width is stored verbatim; negative or non-finite values are left for the
72    /// renderer to reject or normalize.
73    ///
74    /// # Examples
75    ///
76    /// ```
77    /// use ailloli_ui_core::{Color, LineCap, StrokeStyle};
78    /// let stroke = StrokeStyle::new(2.0, Color::WHITE);
79    /// assert_eq!((stroke.width, stroke.cap), (2.0, LineCap::Butt));
80    /// ```
81    pub fn new(width: f32, color: Color) -> Self {
82        Self {
83            width,
84            color,
85            ..Self::default()
86        }
87    }
88}
89
90impl Default for StrokeStyle {
91    fn default() -> Self {
92        Self {
93            color: Color::BLACK,
94            width: 1.0,
95            cap: LineCap::Butt,
96            join: LineJoin::Bevel,
97            miter_limit: 4.0,
98        }
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    //! Locks the default width, color, cap, join, and miter limit.
105
106    use super::*;
107
108    #[test]
109    fn stroke_style_default_is_stable() {
110        let style = StrokeStyle::default();
111
112        assert_eq!(style.color, Color::BLACK);
113        assert_eq!(style.width, 1.0);
114        assert_eq!(style.cap, LineCap::Butt);
115        assert_eq!(style.join, LineJoin::Bevel);
116        assert_eq!(style.miter_limit, 4.0);
117    }
118}