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))]
44#[derive(Clone, Debug, PartialEq)]
45pub enum Fill {
46 Color(Color),
48 Shader(Box<ShaderFill>),
50 LinearGradient(Box<LinearGradient>),
52 RadialGradient(Box<RadialGradient>),
54 ConicGradient(Box<ConicGradient>),
56}
57
58impl Fill {
59 pub fn set_a(&mut self, a: u8) {
60 if let Fill::Color(color) = self {
61 if *color != Color::TRANSPARENT {
63 *color = color.with_a(a);
64 }
65 }
66 }
67
68 pub fn as_color(&self) -> Option<Color> {
70 match self {
71 Fill::Color(color) => Some(*color),
72 _ => None,
73 }
74 }
75
76 pub fn apply_to_paint(&self, paint: &mut Paint, area: Area) {
77 match &self {
78 Fill::Color(color) => {
79 paint.set_color(*color);
80 }
81 Fill::LinearGradient(gradient) => {
82 paint.set_shader(gradient.prepare_shader(area));
83 }
84 Fill::RadialGradient(gradient) => {
85 paint.set_shader(gradient.prepare_shader(area));
86 }
87 Fill::ConicGradient(gradient) => {
88 paint.set_shader(gradient.prepare_shader(area));
89 }
90 Fill::Shader(shader) => {
91 paint.set_shader(shader.prepare_shader(area));
92 }
93 }
94 }
95}
96
97impl Default for Fill {
98 fn default() -> Self {
99 Self::Color(Color::default())
100 }
101}
102
103impl Hash for Fill {
104 fn hash<H: Hasher>(&self, state: &mut H) {
105 discriminant(self).hash(state);
106 match self {
107 Fill::Color(color) => color.hash(state),
108 Fill::Shader(shader) => shader.hash(state),
109 Fill::LinearGradient(gradient) => gradient.hash(state),
110 Fill::RadialGradient(gradient) => gradient.hash(state),
111 Fill::ConicGradient(gradient) => gradient.hash(state),
112 }
113 }
114}
115
116impl From<Color> for Fill {
117 fn from(color: Color) -> Self {
118 Fill::Color(color)
119 }
120}
121
122impl fmt::Display for Fill {
123 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124 match self {
125 Self::Color(color) => color.fmt(f),
126 Self::Shader(shader) => shader.as_ref().fmt(f),
127 Self::LinearGradient(gradient) => gradient.as_ref().fmt(f),
128 Self::RadialGradient(gradient) => gradient.as_ref().fmt(f),
129 Self::ConicGradient(gradient) => gradient.as_ref().fmt(f),
130 }
131 }
132}