Skip to main content

freya_core/style/
fill.rs

1use std::{
2    fmt::{
3        self,
4        Pointer,
5    },
6    hash::{
7        Hash,
8        Hasher,
9    },
10    mem::discriminant,
11};
12
13use freya_engine::prelude::Paint;
14use torin::prelude::Area;
15
16use crate::{
17    prelude::Color,
18    style::{
19        gradient::{
20            ConicGradient,
21            LinearGradient,
22            RadialGradient,
23        },
24        shader::ShaderFill,
25    },
26};
27
28#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
29#[derive(Clone, Debug, PartialEq)]
30pub enum Fill {
31    Color(Color),
32    Shader(Box<ShaderFill>),
33    LinearGradient(Box<LinearGradient>),
34    RadialGradient(Box<RadialGradient>),
35    ConicGradient(Box<ConicGradient>),
36}
37
38impl Fill {
39    pub fn set_a(&mut self, a: u8) {
40        if let Fill::Color(color) = self {
41            // Only actually change the alpha if its non-transparent
42            if *color != Color::TRANSPARENT {
43                *color = color.with_a(a);
44            }
45        }
46    }
47
48    /// Returns the inner [Color] when this is a [Fill::Color].
49    pub fn as_color(&self) -> Option<Color> {
50        match self {
51            Fill::Color(color) => Some(*color),
52            _ => None,
53        }
54    }
55
56    pub fn apply_to_paint(&self, paint: &mut Paint, area: Area) {
57        match &self {
58            Fill::Color(color) => {
59                paint.set_color(*color);
60            }
61            Fill::LinearGradient(gradient) => {
62                paint.set_shader(gradient.prepare_shader(area));
63            }
64            Fill::RadialGradient(gradient) => {
65                paint.set_shader(gradient.prepare_shader(area));
66            }
67            Fill::ConicGradient(gradient) => {
68                paint.set_shader(gradient.prepare_shader(area));
69            }
70            Fill::Shader(shader) => {
71                paint.set_shader(shader.prepare_shader(area));
72            }
73        }
74    }
75}
76
77impl Default for Fill {
78    fn default() -> Self {
79        Self::Color(Color::default())
80    }
81}
82
83impl Hash for Fill {
84    fn hash<H: Hasher>(&self, state: &mut H) {
85        discriminant(self).hash(state);
86        match self {
87            Fill::Color(color) => color.hash(state),
88            Fill::Shader(shader) => shader.hash(state),
89            Fill::LinearGradient(gradient) => gradient.hash(state),
90            Fill::RadialGradient(gradient) => gradient.hash(state),
91            Fill::ConicGradient(gradient) => gradient.hash(state),
92        }
93    }
94}
95
96impl From<Color> for Fill {
97    fn from(color: Color) -> Self {
98        Fill::Color(color)
99    }
100}
101
102impl fmt::Display for Fill {
103    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104        match self {
105            Self::Color(color) => color.fmt(f),
106            Self::Shader(shader) => shader.as_ref().fmt(f),
107            Self::LinearGradient(gradient) => gradient.as_ref().fmt(f),
108            Self::RadialGradient(gradient) => gradient.as_ref().fmt(f),
109            Self::ConicGradient(gradient) => gradient.as_ref().fmt(f),
110        }
111    }
112}