Skip to main content

model/
line.rs

1#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
2#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3pub enum LineStylePreset {
4    /// Solid line (no pattern).
5    #[default]
6    Solid,
7    /// Standard dash: `[8, 4]`.
8    Dash,
9    /// Dotted: `[2, 3]`.
10    Dot,
11    /// Dash-dot: `[8, 4, 2, 4]`.
12    DashDot,
13    /// Dash-dot-dot: `[8, 4, 2, 4, 2, 4]`.
14    DashDotDot,
15    /// Short dash: `[4, 3]`.
16    ShortDash,
17    /// Short dot (dense dots): `[1, 2]`.
18    ShortDot,
19    /// Short dash-dot: `[4, 3, 1, 3]`.
20    ShortDashDot,
21    /// Long dash: `[14, 4]`.
22    LongDash,
23    /// Long dash-dot: `[14, 4, 2, 4]`.
24    LongDashDot,
25    /// Long dash-dot-dot: `[14, 4, 2, 4, 2, 4]`.
26    LongDashDotDot,
27}
28
29impl LineStylePreset {
30    /// Dash pattern as sequential `[on, off, ...]` pixel lengths at 1× scale.
31    /// Empty slice = solid. Consumers (CPU raster dash, GPU `Style.dash`)
32    /// apply their own scale factor to each entry.
33    pub fn pattern(&self) -> &'static [f32] {
34        match self {
35            LineStylePreset::Solid => &[],
36            LineStylePreset::Dash => &[8.0, 4.0],
37            LineStylePreset::Dot => &[2.0, 3.0],
38            LineStylePreset::DashDot => &[8.0, 4.0, 2.0, 4.0],
39            LineStylePreset::DashDotDot => &[8.0, 4.0, 2.0, 4.0, 2.0, 4.0],
40            LineStylePreset::ShortDash => &[4.0, 3.0],
41            LineStylePreset::ShortDot => &[1.0, 2.0],
42            LineStylePreset::ShortDashDot => &[4.0, 3.0, 1.0, 3.0],
43            LineStylePreset::LongDash => &[14.0, 4.0],
44            LineStylePreset::LongDashDot => &[14.0, 4.0, 2.0, 4.0],
45            LineStylePreset::LongDashDotDot => &[14.0, 4.0, 2.0, 4.0, 2.0, 4.0],
46        }
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn solid_pattern_is_empty() {
56        assert!(LineStylePreset::Solid.pattern().is_empty());
57    }
58
59    #[test]
60    fn dash_presets_are_positive_on_off_pairs() {
61        for preset in [
62            LineStylePreset::Dash,
63            LineStylePreset::Dot,
64            LineStylePreset::DashDot,
65            LineStylePreset::DashDotDot,
66            LineStylePreset::ShortDash,
67            LineStylePreset::ShortDot,
68            LineStylePreset::ShortDashDot,
69            LineStylePreset::LongDash,
70            LineStylePreset::LongDashDot,
71            LineStylePreset::LongDashDotDot,
72        ] {
73            let pattern = preset.pattern();
74            assert!(!pattern.is_empty());
75            assert_eq!(pattern.len() % 2, 0, "{preset:?}");
76            assert!(pattern.iter().all(|length| *length > 0.0), "{preset:?}");
77        }
78    }
79}