summaryrefslogtreecommitdiffstats
path: root/graphics/src/widget/canvas/gradient/linear.rs
blob: 37533e190a1c1a1dd6aa138799aa7b17f5baa37f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//! A linear color gradient.
use iced_native::{Color, Point};

use crate::gradient::ColorStop;

use super::Gradient;

/// A linear gradient that can be used in the style of [`super::Fill`] or [`super::Stroke`].
#[derive(Debug, Clone, PartialEq)]
pub struct Linear {
    /// The point where the linear gradient begins.
    pub start: Point,
    /// The point where the linear gradient ends.
    pub end: Point,
    /// [`ColorStop`]s along the linear gradient path.
    pub color_stops: Vec<ColorStop>,
}

/// A [`Linear`] builder.
#[derive(Debug)]
pub struct Builder {
    start: Point,
    end: Point,
    stops: Vec<(f32, Color)>,
    valid: bool,
}

impl Builder {
    /// Creates a new [`Builder`].
    pub fn new(start: Point, end: Point) -> Self {
        Self {
            start,
            end,
            stops: vec![],
            valid: true,
        }
    }

    /// Adds a new stop, defined by an offset and a color, to the gradient.
    ///
    /// `offset` must be between `0.0` and `1.0`.
    pub fn add_stop(mut self, offset: f32, color: Color) -> Self {
        if !(0.0..=1.0).contains(&offset) {
            self.valid = false;
        }

        self.stops.push((offset, color));
        self
    }

    /// Builds the linear [`Gradient`] of this [`Builder`].
    ///
    /// Returns `None` if no stops were added to the builder or
    /// if stops not between 0.0 and 1.0 were added.
    pub fn build(self) -> Option<Gradient> {
        if self.stops.is_empty() || !self.valid {
            return None;
        }

        Some(Gradient::Linear(Linear {
            start: self.start,
            end: self.end,
            color_stops: self
                .stops
                .into_iter()
                .map(|f| ColorStop {
                    offset: f.0,
                    color: f.1,
                })
                .collect(),
        }))
    }
}