1use crate::{color::Color, geometry::Point, render_effect::TileMode};
4
5#[derive(Clone, Debug, PartialEq)]
6pub enum Brush {
7 Solid(Color),
8 LinearGradient {
9 colors: Vec<Color>,
10 stops: Option<Vec<f32>>,
11 start: Point,
12 end: Point,
13 tile_mode: TileMode,
14 },
15 RadialGradient {
16 colors: Vec<Color>,
17 stops: Option<Vec<f32>>,
18 center: Point,
19 radius: f32,
20 tile_mode: TileMode,
21 },
22 SweepGradient {
23 colors: Vec<Color>,
24 stops: Option<Vec<f32>>,
25 center: Point,
26 },
27}
28
29fn split_color_stops(color_stops: Vec<(f32, Color)>) -> (Vec<Color>, Vec<f32>) {
30 let mut colors = Vec::with_capacity(color_stops.len());
31 let mut stops = Vec::with_capacity(color_stops.len());
32 for (stop, color) in color_stops {
33 colors.push(color);
34 stops.push(stop);
35 }
36 (colors, stops)
37}
38
39impl From<Color> for Brush {
42 fn from(color: Color) -> Self {
43 Brush::Solid(color)
44 }
45}
46
47impl Brush {
48 pub fn solid(color: Color) -> Self {
49 Brush::Solid(color)
50 }
51
52 pub fn linear_gradient(colors: Vec<Color>) -> Self {
55 Self::linear_gradient_with_tile_mode(
56 colors,
57 Point { x: 0.0, y: 0.0 },
58 Point {
59 x: f32::INFINITY,
60 y: f32::INFINITY,
61 },
62 TileMode::Clamp,
63 )
64 }
65
66 pub fn linear_gradient_range(colors: Vec<Color>, start: Point, end: Point) -> Self {
67 Self::linear_gradient_with_tile_mode(colors, start, end, TileMode::Clamp)
68 }
69
70 pub fn linear_gradient_with_tile_mode(
71 colors: Vec<Color>,
72 start: Point,
73 end: Point,
74 tile_mode: TileMode,
75 ) -> Self {
76 Brush::LinearGradient {
77 colors,
78 stops: None,
79 start,
80 end,
81 tile_mode,
82 }
83 }
84
85 pub fn linear_gradient_stops(
86 color_stops: Vec<(f32, Color)>,
87 start: Point,
88 end: Point,
89 tile_mode: TileMode,
90 ) -> Self {
91 let (colors, stops) = split_color_stops(color_stops);
92 Brush::LinearGradient {
93 colors,
94 stops: Some(stops),
95 start,
96 end,
97 tile_mode,
98 }
99 }
100
101 pub fn vertical_gradient(colors: Vec<Color>, start_y: f32, end_y: f32) -> Self {
102 Self::vertical_gradient_tiled(colors, start_y, end_y, TileMode::Clamp)
103 }
104
105 pub fn vertical_gradient_tiled(
106 colors: Vec<Color>,
107 start_y: f32,
108 end_y: f32,
109 tile_mode: TileMode,
110 ) -> Self {
111 Self::linear_gradient_with_tile_mode(
112 colors,
113 Point { x: 0.0, y: start_y },
114 Point { x: 0.0, y: end_y },
115 tile_mode,
116 )
117 }
118
119 pub fn vertical_gradient_default(colors: Vec<Color>) -> Self {
120 Self::vertical_gradient_tiled(colors, 0.0, f32::INFINITY, TileMode::Clamp)
121 }
122
123 pub fn vertical_gradient_stops(
124 color_stops: Vec<(f32, Color)>,
125 start_y: f32,
126 end_y: f32,
127 tile_mode: TileMode,
128 ) -> Self {
129 Self::linear_gradient_stops(
130 color_stops,
131 Point { x: 0.0, y: start_y },
132 Point { x: 0.0, y: end_y },
133 tile_mode,
134 )
135 }
136
137 pub fn horizontal_gradient(colors: Vec<Color>, start_x: f32, end_x: f32) -> Self {
138 Self::horizontal_gradient_tiled(colors, start_x, end_x, TileMode::Clamp)
139 }
140
141 pub fn horizontal_gradient_tiled(
142 colors: Vec<Color>,
143 start_x: f32,
144 end_x: f32,
145 tile_mode: TileMode,
146 ) -> Self {
147 Self::linear_gradient_with_tile_mode(
148 colors,
149 Point { x: start_x, y: 0.0 },
150 Point { x: end_x, y: 0.0 },
151 tile_mode,
152 )
153 }
154
155 pub fn horizontal_gradient_default(colors: Vec<Color>) -> Self {
156 Self::horizontal_gradient_tiled(colors, 0.0, f32::INFINITY, TileMode::Clamp)
157 }
158
159 pub fn horizontal_gradient_stops(
160 color_stops: Vec<(f32, Color)>,
161 start_x: f32,
162 end_x: f32,
163 tile_mode: TileMode,
164 ) -> Self {
165 Self::linear_gradient_stops(
166 color_stops,
167 Point { x: start_x, y: 0.0 },
168 Point { x: end_x, y: 0.0 },
169 tile_mode,
170 )
171 }
172
173 pub fn radial_gradient(colors: Vec<Color>, center: Point, radius: f32) -> Self {
174 Self::radial_gradient_tiled(colors, center, radius, TileMode::Clamp)
175 }
176
177 pub fn radial_gradient_tiled(
178 colors: Vec<Color>,
179 center: Point,
180 radius: f32,
181 tile_mode: TileMode,
182 ) -> Self {
183 Brush::RadialGradient {
184 colors,
185 stops: None,
186 center,
187 radius,
188 tile_mode,
189 }
190 }
191
192 pub fn radial_gradient_stops(
193 color_stops: Vec<(f32, Color)>,
194 center: Point,
195 radius: f32,
196 tile_mode: TileMode,
197 ) -> Self {
198 let (colors, stops) = split_color_stops(color_stops);
199 Brush::RadialGradient {
200 colors,
201 stops: Some(stops),
202 center,
203 radius,
204 tile_mode,
205 }
206 }
207
208 pub fn sweep_gradient(colors: Vec<Color>, center: Point) -> Self {
209 Brush::SweepGradient {
210 colors,
211 stops: None,
212 center,
213 }
214 }
215
216 pub fn sweep_gradient_stops(color_stops: Vec<(f32, Color)>, center: Point) -> Self {
217 let (colors, stops) = split_color_stops(color_stops);
218 Brush::SweepGradient {
219 colors,
220 stops: Some(stops),
221 center,
222 }
223 }
224}
225
226#[cfg(test)]
227#[path = "tests/brush_tests.rs"]
228mod tests;