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 if *color != Color::TRANSPARENT {
43 *color = color.with_a(a);
44 }
45 }
46 }
47
48 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}