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 Brush {
40 pub fn solid(color: Color) -> Self {
41 Brush::Solid(color)
42 }
43
44 pub fn linear_gradient(colors: Vec<Color>) -> Self {
47 Self::linear_gradient_with_tile_mode(
48 colors,
49 Point { x: 0.0, y: 0.0 },
50 Point {
51 x: f32::INFINITY,
52 y: f32::INFINITY,
53 },
54 TileMode::Clamp,
55 )
56 }
57
58 pub fn linear_gradient_range(colors: Vec<Color>, start: Point, end: Point) -> Self {
59 Self::linear_gradient_with_tile_mode(colors, start, end, TileMode::Clamp)
60 }
61
62 pub fn linear_gradient_with_tile_mode(
63 colors: Vec<Color>,
64 start: Point,
65 end: Point,
66 tile_mode: TileMode,
67 ) -> Self {
68 Brush::LinearGradient {
69 colors,
70 stops: None,
71 start,
72 end,
73 tile_mode,
74 }
75 }
76
77 pub fn linear_gradient_stops(
78 color_stops: Vec<(f32, Color)>,
79 start: Point,
80 end: Point,
81 tile_mode: TileMode,
82 ) -> Self {
83 let (colors, stops) = split_color_stops(color_stops);
84 Brush::LinearGradient {
85 colors,
86 stops: Some(stops),
87 start,
88 end,
89 tile_mode,
90 }
91 }
92
93 pub fn vertical_gradient(colors: Vec<Color>, start_y: f32, end_y: f32) -> Self {
94 Self::vertical_gradient_tiled(colors, start_y, end_y, TileMode::Clamp)
95 }
96
97 pub fn vertical_gradient_tiled(
98 colors: Vec<Color>,
99 start_y: f32,
100 end_y: f32,
101 tile_mode: TileMode,
102 ) -> Self {
103 Self::linear_gradient_with_tile_mode(
104 colors,
105 Point { x: 0.0, y: start_y },
106 Point { x: 0.0, y: end_y },
107 tile_mode,
108 )
109 }
110
111 pub fn vertical_gradient_default(colors: Vec<Color>) -> Self {
112 Self::vertical_gradient_tiled(colors, 0.0, f32::INFINITY, TileMode::Clamp)
113 }
114
115 pub fn vertical_gradient_stops(
116 color_stops: Vec<(f32, Color)>,
117 start_y: f32,
118 end_y: f32,
119 tile_mode: TileMode,
120 ) -> Self {
121 Self::linear_gradient_stops(
122 color_stops,
123 Point { x: 0.0, y: start_y },
124 Point { x: 0.0, y: end_y },
125 tile_mode,
126 )
127 }
128
129 pub fn horizontal_gradient(colors: Vec<Color>, start_x: f32, end_x: f32) -> Self {
130 Self::horizontal_gradient_tiled(colors, start_x, end_x, TileMode::Clamp)
131 }
132
133 pub fn horizontal_gradient_tiled(
134 colors: Vec<Color>,
135 start_x: f32,
136 end_x: f32,
137 tile_mode: TileMode,
138 ) -> Self {
139 Self::linear_gradient_with_tile_mode(
140 colors,
141 Point { x: start_x, y: 0.0 },
142 Point { x: end_x, y: 0.0 },
143 tile_mode,
144 )
145 }
146
147 pub fn horizontal_gradient_default(colors: Vec<Color>) -> Self {
148 Self::horizontal_gradient_tiled(colors, 0.0, f32::INFINITY, TileMode::Clamp)
149 }
150
151 pub fn horizontal_gradient_stops(
152 color_stops: Vec<(f32, Color)>,
153 start_x: f32,
154 end_x: f32,
155 tile_mode: TileMode,
156 ) -> Self {
157 Self::linear_gradient_stops(
158 color_stops,
159 Point { x: start_x, y: 0.0 },
160 Point { x: end_x, y: 0.0 },
161 tile_mode,
162 )
163 }
164
165 pub fn radial_gradient(colors: Vec<Color>, center: Point, radius: f32) -> Self {
166 Self::radial_gradient_tiled(colors, center, radius, TileMode::Clamp)
167 }
168
169 pub fn radial_gradient_tiled(
170 colors: Vec<Color>,
171 center: Point,
172 radius: f32,
173 tile_mode: TileMode,
174 ) -> Self {
175 Brush::RadialGradient {
176 colors,
177 stops: None,
178 center,
179 radius,
180 tile_mode,
181 }
182 }
183
184 pub fn radial_gradient_stops(
185 color_stops: Vec<(f32, Color)>,
186 center: Point,
187 radius: f32,
188 tile_mode: TileMode,
189 ) -> Self {
190 let (colors, stops) = split_color_stops(color_stops);
191 Brush::RadialGradient {
192 colors,
193 stops: Some(stops),
194 center,
195 radius,
196 tile_mode,
197 }
198 }
199
200 pub fn sweep_gradient(colors: Vec<Color>, center: Point) -> Self {
201 Brush::SweepGradient {
202 colors,
203 stops: None,
204 center,
205 }
206 }
207
208 pub fn sweep_gradient_stops(color_stops: Vec<(f32, Color)>, center: Point) -> Self {
209 let (colors, stops) = split_color_stops(color_stops);
210 Brush::SweepGradient {
211 colors,
212 stops: Some(stops),
213 center,
214 }
215 }
216}
217
218#[cfg(test)]
219#[path = "tests/brush_tests.rs"]
220mod tests;