1use crate::{
2 gradient, scalar, shaders, Color, Color4f, ColorSpace, Matrix, Point, Shader, TileMode,
3};
4
5pub use gradient::{interpolation, Colors as GradientColors, Gradient, Interpolation};
6
7impl From<Flags> for Interpolation {
8 fn from(flags: Flags) -> Self {
9 let in_premul = if flags.contains(Flags::INTERPOLATE_COLORS_IN_PREMUL) {
10 interpolation::InPremul::Yes
11 } else {
12 interpolation::InPremul::No
13 };
14 Self {
15 in_premul,
16 color_space: interpolation::ColorSpace::Destination,
17 hue_method: interpolation::HueMethod::Shorter,
18 }
19 }
20}
21
22impl Shader {
23 #[deprecated(since = "0.93.0", note = "Use shaders::linear_gradient() instead")]
24 pub fn linear_gradient<'a>(
25 points: (impl Into<Point>, impl Into<Point>),
26 colors: impl Into<GradientShaderColors<'a>>,
27 pos: impl Into<Option<&'a [scalar]>>,
28 mode: TileMode,
29 flags: impl Into<Option<Flags>>,
30 local_matrix: impl Into<Option<&'a Matrix>>,
31 ) -> Option<Self> {
32 linear(points, colors, pos, mode, flags, local_matrix)
33 }
34
35 #[deprecated(since = "0.93.0", note = "Use shaders::linear_gradient() instead")]
36 pub fn linear_gradient_with_interpolation<'a>(
37 points: (impl Into<Point>, impl Into<Point>),
38 colors: (&'a [Color4f], impl Into<Option<ColorSpace>>),
39 pos: impl Into<Option<&'a [scalar]>>,
40 mode: TileMode,
41 interpolation: impl Into<Interpolation>,
42 local_matrix: impl Into<Option<&'a Matrix>>,
43 ) -> Option<Self> {
44 linear_with_interpolation(points, colors, pos, mode, interpolation, local_matrix)
45 }
46
47 #[deprecated(since = "0.93.0", note = "Use shaders::radial_gradient() instead")]
48 pub fn radial_gradient<'a>(
49 center: impl Into<Point>,
50 radius: scalar,
51 colors: impl Into<GradientShaderColors<'a>>,
52 pos: impl Into<Option<&'a [scalar]>>,
53 mode: TileMode,
54 flags: impl Into<Option<self::Flags>>,
55 local_matrix: impl Into<Option<&'a Matrix>>,
56 ) -> Option<Self> {
57 radial(center, radius, colors, pos, mode, flags, local_matrix)
58 }
59
60 #[deprecated(since = "0.93.0", note = "Use shaders::radial_gradient() instead")]
61 #[allow(clippy::too_many_arguments)]
62 pub fn radial_gradient_with_interpolation<'a>(
63 center_and_radius: (impl Into<Point>, scalar),
64 colors: (&'a [Color4f], impl Into<Option<ColorSpace>>),
65 pos: impl Into<Option<&'a [scalar]>>,
66 mode: TileMode,
67 interpolation: impl Into<Interpolation>,
68 local_matrix: impl Into<Option<&'a Matrix>>,
69 ) -> Option<Shader> {
70 radial_with_interpolation(
71 center_and_radius,
72 colors,
73 pos,
74 mode,
75 interpolation,
76 local_matrix,
77 )
78 }
79
80 #[deprecated(
81 since = "0.93.0",
82 note = "Use shaders::two_point_conical_gradient() instead"
83 )]
84 #[allow(clippy::too_many_arguments)]
85 pub fn two_point_conical_gradient<'a>(
86 start: impl Into<Point>,
87 start_radius: scalar,
88 end: impl Into<Point>,
89 end_radius: scalar,
90 colors: impl Into<GradientShaderColors<'a>>,
91 pos: impl Into<Option<&'a [scalar]>>,
92 mode: TileMode,
93 flags: impl Into<Option<self::Flags>>,
94 local_matrix: impl Into<Option<&'a Matrix>>,
95 ) -> Option<Self> {
96 two_point_conical(
97 start,
98 start_radius,
99 end,
100 end_radius,
101 colors,
102 pos,
103 mode,
104 flags,
105 local_matrix,
106 )
107 }
108
109 #[deprecated(
110 since = "0.93.0",
111 note = "Use shaders::two_point_conical_gradient() instead"
112 )]
113 pub fn two_point_conical_gradient_with_interpolation<'a>(
114 start_and_radius: (impl Into<Point>, scalar),
115 end_and_radius: (impl Into<Point>, scalar),
116 colors: (&'a [Color4f], impl Into<Option<ColorSpace>>),
117 pos: impl Into<Option<&'a [scalar]>>,
118 mode: TileMode,
119 interpolation: impl Into<Interpolation>,
120 local_matrix: impl Into<Option<&'a Matrix>>,
121 ) -> Option<Shader> {
122 two_point_conical_with_interpolation(
123 start_and_radius,
124 end_and_radius,
125 colors,
126 pos,
127 mode,
128 interpolation,
129 local_matrix,
130 )
131 }
132
133 #[deprecated(since = "0.93.0", note = "Use shaders::sweep_gradient() instead")]
134 pub fn sweep_gradient<'a>(
135 center: impl Into<Point>,
136 colors: impl Into<GradientShaderColors<'a>>,
137 pos: impl Into<Option<&'a [scalar]>>,
138 mode: TileMode,
139 angles: impl Into<Option<(scalar, scalar)>>,
140 flags: impl Into<Option<self::Flags>>,
141 local_matrix: impl Into<Option<&'a Matrix>>,
142 ) -> Option<Self> {
143 sweep(center, colors, pos, mode, angles, flags, local_matrix)
144 }
145
146 #[deprecated(since = "0.93.0", note = "Use shaders::sweep_gradient() instead")]
147 pub fn sweep_gradient_with_interpolation<'a>(
148 center: impl Into<Point>,
149 colors: (&'a [Color4f], impl Into<Option<ColorSpace>>),
150 pos: impl Into<Option<&'a [scalar]>>,
151 mode: TileMode,
152 angles: impl Into<Option<(scalar, scalar)>>,
153 interpolation: impl Into<Interpolation>,
154 local_matrix: impl Into<Option<&'a Matrix>>,
155 ) -> Option<Shader> {
156 sweep_with_interpolation(
157 center,
158 colors,
159 pos,
160 mode,
161 angles,
162 interpolation,
163 local_matrix,
164 )
165 }
166}
167
168bitflags! {
169 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
170 pub struct Flags: u32 {
171 const INTERPOLATE_COLORS_IN_PREMUL = 1 << 0;
172 }
173}
174
175impl Default for self::Flags {
176 fn default() -> Self {
177 Self::empty()
178 }
179}
180
181pub fn linear<'a>(
182 points: (impl Into<Point>, impl Into<Point>),
183 colors: impl Into<GradientShaderColors<'a>>,
184 pos: impl Into<Option<&'a [scalar]>>,
185 mode: TileMode,
186 flags: impl Into<Option<Flags>>,
187 local_matrix: impl Into<Option<&'a Matrix>>,
188) -> Option<Shader> {
189 let colors = colors.into();
190 let pos = pos.into();
191 let flags = flags.into().unwrap_or_default();
192
193 match colors {
194 GradientShaderColors::Colors(colors) => {
195 let colors4f: Vec<Color4f> = colors.iter().map(|c| Color4f::from(*c)).collect();
197 let grad_colors = GradientColors::new(&colors4f, pos, mode, None);
198 let grad = Gradient::new(grad_colors, flags);
199 shaders::linear_gradient(points, &grad, local_matrix)
200 }
201 GradientShaderColors::ColorsInSpace(colors, color_space) => linear_with_interpolation(
202 points,
203 (colors, color_space),
204 pos,
205 mode,
206 flags,
207 local_matrix,
208 ),
209 }
210}
211
212pub fn linear_with_interpolation<'a>(
213 points: (impl Into<Point>, impl Into<Point>),
214 (colors, color_space): (&'a [Color4f], impl Into<Option<ColorSpace>>),
215 pos: impl Into<Option<&'a [scalar]>>,
216 mode: TileMode,
217 interpolation: impl Into<Interpolation>,
218 local_matrix: impl Into<Option<&'a Matrix>>,
219) -> Option<Shader> {
220 let pos = pos.into();
221 let color_space = color_space.into();
222 let grad_colors = GradientColors::new(colors, pos, mode, color_space);
223 let grad = Gradient::new(grad_colors, interpolation);
224 shaders::linear_gradient(points, &grad, local_matrix)
225}
226
227pub fn radial<'a>(
228 center: impl Into<Point>,
229 radius: scalar,
230 colors: impl Into<GradientShaderColors<'a>>,
231 pos: impl Into<Option<&'a [scalar]>>,
232 mode: TileMode,
233 flags: impl Into<Option<self::Flags>>,
234 local_matrix: impl Into<Option<&'a Matrix>>,
235) -> Option<Shader> {
236 let colors = colors.into();
237 let pos = pos.into();
238 let flags = flags.into().unwrap_or_default();
239
240 match colors {
241 GradientShaderColors::Colors(colors) => {
242 let colors4f: Vec<Color4f> = colors.iter().map(|c| Color4f::from(*c)).collect();
243 let grad_colors = GradientColors::new(&colors4f, pos, mode, None);
244 let grad = Gradient::new(grad_colors, flags);
245 shaders::radial_gradient((center, radius), &grad, local_matrix)
246 }
247 GradientShaderColors::ColorsInSpace(colors, color_space) => radial_with_interpolation(
248 (center, radius),
249 (colors, color_space),
250 pos,
251 mode,
252 flags,
253 local_matrix,
254 ),
255 }
256}
257
258pub fn radial_with_interpolation<'a>(
259 (center, radius): (impl Into<Point>, scalar),
260 (colors, color_space): (&'a [Color4f], impl Into<Option<ColorSpace>>),
261 pos: impl Into<Option<&'a [scalar]>>,
262 mode: TileMode,
263 interpolation: impl Into<Interpolation>,
264 local_matrix: impl Into<Option<&'a Matrix>>,
265) -> Option<Shader> {
266 let pos = pos.into();
267 let color_space = color_space.into();
268 let grad_colors = GradientColors::new(colors, pos, mode, color_space);
269 let grad = Gradient::new(grad_colors, interpolation);
270 shaders::radial_gradient((center, radius), &grad, local_matrix)
271}
272
273#[allow(clippy::too_many_arguments)]
274pub fn two_point_conical<'a>(
275 start: impl Into<Point>,
276 start_radius: scalar,
277 end: impl Into<Point>,
278 end_radius: scalar,
279 colors: impl Into<GradientShaderColors<'a>>,
280 pos: impl Into<Option<&'a [scalar]>>,
281 mode: TileMode,
282 flags: impl Into<Option<self::Flags>>,
283 local_matrix: impl Into<Option<&'a Matrix>>,
284) -> Option<Shader> {
285 let colors = colors.into();
286 let pos = pos.into();
287 let flags = flags.into().unwrap_or_default();
288
289 match colors {
290 GradientShaderColors::Colors(colors) => {
291 let colors4f: Vec<Color4f> = colors.iter().map(|c| Color4f::from(*c)).collect();
292 let grad_colors = GradientColors::new(&colors4f, pos, mode, None);
293 let grad = Gradient::new(grad_colors, flags);
294 shaders::two_point_conical_gradient(
295 (start, start_radius),
296 (end, end_radius),
297 &grad,
298 local_matrix,
299 )
300 }
301 GradientShaderColors::ColorsInSpace(colors, color_space) => {
302 two_point_conical_with_interpolation(
303 (start, start_radius),
304 (end, end_radius),
305 (colors, color_space),
306 pos,
307 mode,
308 flags,
309 local_matrix,
310 )
311 }
312 }
313}
314
315pub fn two_point_conical_with_interpolation<'a>(
316 (start, start_radius): (impl Into<Point>, scalar),
317 (end, end_radius): (impl Into<Point>, scalar),
318 (colors, color_space): (&'a [Color4f], impl Into<Option<ColorSpace>>),
319 pos: impl Into<Option<&'a [scalar]>>,
320 mode: TileMode,
321 interpolation: impl Into<Interpolation>,
322 local_matrix: impl Into<Option<&'a Matrix>>,
323) -> Option<Shader> {
324 let pos = pos.into();
325 let color_space = color_space.into();
326 let grad_colors = GradientColors::new(colors, pos, mode, color_space);
327 let grad = Gradient::new(grad_colors, interpolation);
328 shaders::two_point_conical_gradient(
329 (start, start_radius),
330 (end, end_radius),
331 &grad,
332 local_matrix,
333 )
334}
335
336pub fn sweep<'a>(
337 center: impl Into<Point>,
338 colors: impl Into<GradientShaderColors<'a>>,
339 pos: impl Into<Option<&'a [scalar]>>,
340 mode: TileMode,
341 angles: impl Into<Option<(scalar, scalar)>>,
342 flags: impl Into<Option<self::Flags>>,
343 local_matrix: impl Into<Option<&'a Matrix>>,
344) -> Option<Shader> {
345 let colors = colors.into();
346 let pos = pos.into();
347 let angles = angles.into();
348 let flags = flags.into().unwrap_or_default();
349
350 let (start_angle, end_angle) = (
351 angles.map(|a| a.0).unwrap_or(0.0),
352 angles.map(|a| a.1).unwrap_or(360.0),
353 );
354
355 match colors {
356 GradientShaderColors::Colors(colors) => {
357 let colors4f: Vec<Color4f> = colors.iter().map(|c| Color4f::from(*c)).collect();
358 let grad_colors = GradientColors::new(&colors4f, pos, mode, None);
359 let grad = Gradient::new(grad_colors, flags);
360 shaders::sweep_gradient(center, (start_angle, end_angle), &grad, local_matrix)
361 }
362 GradientShaderColors::ColorsInSpace(colors, color_space) => sweep_with_interpolation(
363 center,
364 (colors, color_space),
365 pos,
366 mode,
367 angles,
368 flags,
369 local_matrix,
370 ),
371 }
372}
373
374pub fn sweep_with_interpolation<'a>(
375 center: impl Into<Point>,
376 (colors, color_space): (&'a [Color4f], impl Into<Option<ColorSpace>>),
377 pos: impl Into<Option<&'a [scalar]>>,
378 mode: TileMode,
379 angles: impl Into<Option<(scalar, scalar)>>,
380 interpolation: impl Into<Interpolation>,
381 local_matrix: impl Into<Option<&'a Matrix>>,
382) -> Option<Shader> {
383 let pos = pos.into();
384 let angles = angles.into();
385 let color_space = color_space.into();
386
387 let (start_angle, end_angle) = (
388 angles.map(|a| a.0).unwrap_or(0.0),
389 angles.map(|a| a.1).unwrap_or(360.0),
390 );
391
392 let grad_colors = GradientColors::new(colors, pos, mode, color_space);
393 let grad = Gradient::new(grad_colors, interpolation);
394 shaders::sweep_gradient(center, (start_angle, end_angle), &grad, local_matrix)
395}
396
397#[derive(Debug)]
401pub enum GradientShaderColors<'a> {
402 Colors(&'a [Color]),
403 ColorsInSpace(&'a [Color4f], Option<ColorSpace>),
404}
405
406impl GradientShaderColors<'_> {
407 pub fn len(&self) -> usize {
408 match self {
409 GradientShaderColors::Colors(colors) => colors.len(),
410 GradientShaderColors::ColorsInSpace(colors, _) => colors.len(),
411 }
412 }
413
414 pub fn is_empty(&self) -> bool {
416 self.len() == 0
417 }
418}
419
420impl<'a> From<&'a [Color]> for GradientShaderColors<'a> {
421 fn from(colors: &'a [Color]) -> Self {
422 GradientShaderColors::<'a>::Colors(colors)
423 }
424}
425
426impl<'a> From<(&'a [Color4f], ColorSpace)> for GradientShaderColors<'a> {
427 fn from(c: (&'a [Color4f], ColorSpace)) -> Self {
428 GradientShaderColors::<'a>::ColorsInSpace(c.0, Some(c.1))
429 }
430}
431
432impl<'a> From<(&'a [Color4f], Option<ColorSpace>)> for GradientShaderColors<'a> {
433 fn from(c: (&'a [Color4f], Option<ColorSpace>)) -> Self {
434 GradientShaderColors::<'a>::ColorsInSpace(c.0, c.1)
435 }
436}
437
438impl<'a> From<&'a [Color4f]> for GradientShaderColors<'a> {
439 fn from(c: &'a [Color4f]) -> Self {
440 GradientShaderColors::<'a>::ColorsInSpace(c, None)
441 }
442}