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}