floem_peniko/
style.rs

1// Copyright 2022 The peniko authors.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4use core::borrow::Borrow;
5use smallvec::SmallVec;
6
7/// Describes the rule that determines the interior portion of a shape.
8#[derive(Copy, Clone, PartialEq, Eq, Debug)]
9pub enum Fill {
10    /// Non-zero fill rule.
11    NonZero,
12    /// Even-odd fill rule.
13    EvenOdd,
14}
15
16/// Defines the connection between two segments of a stroke.
17#[derive(Copy, Clone, PartialEq, Eq, Debug)]
18pub enum Join {
19    /// A straight line connecting the segments.
20    Bevel,
21    /// The segments are extended to their natural intersection point.
22    Miter,
23    /// An arc between the segments.
24    Round,
25}
26
27/// Defines the shape to be drawn at the ends of a stroke.
28#[derive(Copy, Clone, PartialEq, Eq, Debug)]
29pub enum Cap {
30    /// Flat cap.
31    Butt,
32    /// Square cap with dimensions equal to half the stroke width.
33    Square,
34    /// Rounded cap with radius equal to half the stroke width.
35    Round,
36}
37
38/// Describes the visual style of a stroke.
39#[derive(Clone, Debug)]
40pub struct Stroke {
41    /// Width of the stroke.
42    pub width: f32,
43    /// Style for connecting segments of the stroke.
44    pub join: Join,
45    /// Limit for miter joins.
46    pub miter_limit: f32,
47    /// Style for capping the beginning of an open subpath.
48    pub start_cap: Cap,
49    /// Style for capping the end of an open subpath.
50    pub end_cap: Cap,
51    /// Lengths of dashes in alternating on/off order.
52    pub dash_pattern: Dashes,
53    /// Offset of the first dash.
54    pub dash_offset: f32,
55    /// True if the stroke width should be affected by the scale of a
56    /// transform.
57    pub scale: bool,
58}
59
60impl Default for Stroke {
61    fn default() -> Self {
62        Self {
63            width: 1.0,
64            join: Join::Round,
65            miter_limit: 4.0,
66            start_cap: Cap::Round,
67            end_cap: Cap::Round,
68            dash_pattern: Default::default(),
69            dash_offset: 0.0,
70            scale: true,
71        }
72    }
73}
74
75impl Stroke {
76    /// Creates a new stroke with the specified width.
77    pub fn new(width: f32) -> Self {
78        Self {
79            width,
80            ..Default::default()
81        }
82    }
83
84    /// Builder method for setting the join style.
85    pub fn with_join(mut self, join: Join) -> Self {
86        self.join = join;
87        self
88    }
89
90    /// Builder method for setting the limit for miter joins.
91    pub fn with_miter_limit(mut self, limit: f32) -> Self {
92        self.miter_limit = limit;
93        self
94    }
95
96    /// Builder method for setting the cap style for the start of the stroke.
97    pub fn with_start_cap(mut self, cap: Cap) -> Self {
98        self.start_cap = cap;
99        self
100    }
101
102    /// Builder method for setting the cap style for the end of the stroke.
103    pub fn with_end_cap(mut self, cap: Cap) -> Self {
104        self.end_cap = cap;
105        self
106    }
107
108    /// Builder method for setting the cap style.
109    pub fn with_caps(mut self, cap: Cap) -> Self {
110        self.start_cap = cap;
111        self.end_cap = cap;
112        self
113    }
114
115    /// Builder method for setting the dashing parameters.
116    pub fn with_dashes<P>(mut self, offset: f32, pattern: P) -> Self
117    where
118        P: IntoIterator,
119        P::Item: Borrow<f32>,
120    {
121        self.dash_offset = offset;
122        self.dash_pattern.clear();
123        self.dash_pattern
124            .extend(pattern.into_iter().map(|dash| *dash.borrow()));
125        self
126    }
127
128    /// Builder method for setting whether or not the stroke should be affected
129    /// by the scale of any applied transform.
130    pub fn with_scale(mut self, yes: bool) -> Self {
131        self.scale = yes;
132        self
133    }
134}
135
136/// Collection of values representing lengths in a dash pattern.
137pub type Dashes = SmallVec<[f32; 4]>;
138
139/// Describes draw style-- either a fill or stroke.
140#[derive(Clone, Debug)]
141pub enum Style {
142    /// Filled draw operation.
143    Fill(Fill),
144    /// Stroked draw operation.
145    Stroke(Stroke),
146}
147
148impl From<Fill> for Style {
149    fn from(fill: Fill) -> Self {
150        Self::Fill(fill)
151    }
152}
153
154impl From<Stroke> for Style {
155    fn from(stroke: Stroke) -> Self {
156        Self::Stroke(stroke)
157    }
158}
159
160/// Reference to a draw style.
161///
162/// This is useful for methods that would like to accept draw styles by reference. Defining
163/// the type as `impl<Into<DrawRef>>` allows accepting types like `&Stroke` or `Fill`
164/// directly without cloning or allocating.
165pub enum StyleRef<'a> {
166    /// Filled draw operation.
167    Fill(Fill),
168    /// Stroked draw operation.
169    Stroke(&'a Stroke),
170}
171
172impl<'a> StyleRef<'a> {
173    /// Converts the reference to an owned draw.
174    pub fn to_owned(&self) -> Style {
175        match self {
176            Self::Fill(fill) => Style::Fill(*fill),
177            Self::Stroke(stroke) => Style::Stroke((*stroke).clone()),
178        }
179    }
180}
181
182impl From<Fill> for StyleRef<'_> {
183    fn from(fill: Fill) -> Self {
184        Self::Fill(fill)
185    }
186}
187
188impl<'a> From<&'a Stroke> for StyleRef<'a> {
189    fn from(stroke: &'a Stroke) -> Self {
190        Self::Stroke(stroke)
191    }
192}
193
194impl<'a> From<&'a Style> for StyleRef<'a> {
195    fn from(draw: &'a Style) -> Self {
196        match draw {
197            Style::Fill(fill) => Self::Fill(*fill),
198            Style::Stroke(stroke) => Self::Stroke(stroke),
199        }
200    }
201}