1use super::{Gradient, Image};
5
6use color::{AlphaColor, ColorSpace, DynamicColor, OpaqueColor, Srgb};
7
8#[derive(Clone, Debug, PartialEq)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub enum Brush {
14 Solid(AlphaColor<Srgb>),
16 Gradient(Gradient),
18 Image(Image),
20}
21
22impl<CS: ColorSpace> From<AlphaColor<CS>> for Brush {
23 fn from(c: AlphaColor<CS>) -> Self {
24 Self::Solid(c.convert())
25 }
26}
27
28impl From<DynamicColor> for Brush {
29 fn from(c: DynamicColor) -> Self {
30 Self::Solid(c.to_alpha_color::<Srgb>())
31 }
32}
33
34impl<CS: ColorSpace> From<OpaqueColor<CS>> for Brush {
35 fn from(c: OpaqueColor<CS>) -> Self {
36 Self::Solid(c.with_alpha(1.).convert())
37 }
38}
39
40impl From<Gradient> for Brush {
41 fn from(g: Gradient) -> Self {
42 Self::Gradient(g)
43 }
44}
45
46impl From<Image> for Brush {
47 fn from(value: Image) -> Self {
48 Self::Image(value)
49 }
50}
51
52impl Default for Brush {
53 fn default() -> Self {
54 Self::Solid(AlphaColor::<Srgb>::TRANSPARENT)
55 }
56}
57
58impl Brush {
59 #[must_use]
61 pub fn with_alpha(self, alpha: f32) -> Self {
62 match self {
63 Self::Solid(color) => color.with_alpha(alpha).into(),
64 Self::Gradient(gradient) => gradient.with_alpha(alpha).into(),
65 Self::Image(image) => image.with_alpha(alpha).into(),
66 }
67 }
68
69 #[must_use]
74 #[doc(alias = "with_alpha_factor")]
75 #[track_caller]
76 pub fn multiply_alpha(self, alpha: f32) -> Self {
77 debug_assert!(
78 alpha.is_finite() && alpha >= 0.0,
79 "A non-finite or negative alpha ({alpha}) is meaningless."
80 );
81 if alpha == 1.0 {
82 self
83 } else {
84 match self {
85 Self::Solid(color) => color.multiply_alpha(alpha).into(),
86 Self::Gradient(gradient) => gradient.multiply_alpha(alpha).into(),
87 Self::Image(image) => image.multiply_alpha(alpha).into(),
88 }
89 }
90 }
91}
92
93#[cfg_attr(
99 target_pointer_width = "32",
100 expect(variant_size_differences, reason = "We're okay with this.")
101)]
102#[derive(Copy, Clone, Debug, PartialEq)]
103pub enum BrushRef<'a> {
104 Solid(AlphaColor<Srgb>),
106 Gradient(&'a Gradient),
108 Image(&'a Image),
110}
111
112impl BrushRef<'_> {
113 #[must_use]
115 pub fn to_owned(&self) -> Brush {
116 match self {
117 Self::Solid(color) => Brush::Solid(*color),
118 Self::Gradient(gradient) => Brush::Gradient((*gradient).clone()),
119 Self::Image(image) => Brush::Image((*image).clone()),
120 }
121 }
122}
123
124impl<CS: ColorSpace> From<AlphaColor<CS>> for BrushRef<'_> {
125 fn from(color: AlphaColor<CS>) -> Self {
126 Self::Solid(color.convert())
127 }
128}
129
130impl From<DynamicColor> for BrushRef<'_> {
131 fn from(color: DynamicColor) -> Self {
132 Self::Solid(color.to_alpha_color::<Srgb>())
133 }
134}
135
136impl<CS: ColorSpace> From<OpaqueColor<CS>> for BrushRef<'_> {
137 fn from(color: OpaqueColor<CS>) -> Self {
138 Self::Solid(color.with_alpha(1.).convert())
139 }
140}
141
142impl<'a, CS: ColorSpace> From<&'a AlphaColor<CS>> for BrushRef<'_> {
143 fn from(color: &'a AlphaColor<CS>) -> Self {
144 Self::Solid((*color).convert())
145 }
146}
147
148impl<'a> From<&'a DynamicColor> for BrushRef<'_> {
149 fn from(color: &'a DynamicColor) -> Self {
150 Self::Solid((*color).to_alpha_color::<Srgb>())
151 }
152}
153
154impl<'a, CS: ColorSpace> From<&'a OpaqueColor<CS>> for BrushRef<'_> {
155 fn from(color: &'a OpaqueColor<CS>) -> Self {
156 Self::Solid((*color).with_alpha(1.).convert())
157 }
158}
159
160impl<'a> From<&'a Gradient> for BrushRef<'a> {
161 fn from(gradient: &'a Gradient) -> Self {
162 Self::Gradient(gradient)
163 }
164}
165
166impl<'a> From<&'a Image> for BrushRef<'a> {
167 fn from(image: &'a Image) -> Self {
168 Self::Image(image)
169 }
170}
171
172impl<'a> From<&'a Brush> for BrushRef<'a> {
173 fn from(brush: &'a Brush) -> Self {
174 match brush {
175 Brush::Solid(color) => Self::Solid(*color),
176 Brush::Gradient(gradient) => Self::Gradient(gradient),
177 Brush::Image(image) => Self::Image(image),
178 }
179 }
180}
181
182#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
185#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
186#[repr(u8)]
187pub enum Extend {
188 #[default]
190 Pad = 0,
191 Repeat = 1,
193 Reflect = 2,
195}