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::{
14 Paint,
15 SkColor,
16};
17use torin::prelude::Area;
18
19use crate::{
20 prelude::Color,
21 style::{
22 gradient::{
23 ConicGradient,
24 LinearGradient,
25 RadialGradient,
26 },
27 shader::ShaderFill,
28 },
29};
30
31#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
45#[derive(Clone, Debug, PartialEq)]
46pub enum Fill {
47 Color(Color),
49 Shader(Box<ShaderFill>),
51 LinearGradient(Box<LinearGradient>),
53 RadialGradient(Box<RadialGradient>),
55 ConicGradient(Box<ConicGradient>),
57}
58
59impl Fill {
60 pub fn set_a(&mut self, a: u8) {
61 if let Fill::Color(color) = self {
62 if *color != Color::TRANSPARENT {
64 *color = color.with_a(a);
65 }
66 }
67 }
68
69 pub fn as_color(&self) -> Option<Color> {
71 match self {
72 Fill::Color(color) => Some(*color),
73 _ => None,
74 }
75 }
76
77 pub fn apply_to_paint(&self, paint: &mut Paint, area: Area) {
78 match &self {
79 Fill::Color(color) => {
80 paint.set_color(*color);
81 }
82 Fill::LinearGradient(gradient) => {
83 paint.set_shader(gradient.prepare_shader(area));
84 }
85 Fill::RadialGradient(gradient) => {
86 paint.set_shader(gradient.prepare_shader(area));
87 }
88 Fill::ConicGradient(gradient) => {
89 paint.set_shader(gradient.prepare_shader(area));
90 }
91 Fill::Shader(shader) => {
92 paint.set_shader(shader.prepare_shader(area));
93 }
94 }
95 }
96}
97
98impl Default for Fill {
99 fn default() -> Self {
100 Self::Color(Color::default())
101 }
102}
103
104impl Hash for Fill {
105 fn hash<H: Hasher>(&self, state: &mut H) {
106 discriminant(self).hash(state);
107 match self {
108 Fill::Color(color) => color.hash(state),
109 Fill::Shader(shader) => shader.hash(state),
110 Fill::LinearGradient(gradient) => gradient.hash(state),
111 Fill::RadialGradient(gradient) => gradient.hash(state),
112 Fill::ConicGradient(gradient) => gradient.hash(state),
113 }
114 }
115}
116
117impl From<Color> for Fill {
118 fn from(color: Color) -> Self {
119 Fill::Color(color)
120 }
121}
122
123impl From<(u8, u8, u8)> for Fill {
124 fn from(color: (u8, u8, u8)) -> Self {
125 Fill::Color(color.into())
126 }
127}
128
129impl From<(u8, u8, u8, f32)> for Fill {
130 fn from(color: (u8, u8, u8, f32)) -> Self {
131 Fill::Color(color.into())
132 }
133}
134
135impl From<(u8, u8, u8, u8)> for Fill {
136 fn from(color: (u8, u8, u8, u8)) -> Self {
137 Fill::Color(color.into())
138 }
139}
140
141impl From<u32> for Fill {
142 fn from(color: u32) -> Self {
143 Fill::Color(color.into())
144 }
145}
146
147impl From<SkColor> for Fill {
148 fn from(color: SkColor) -> Self {
149 Fill::Color(color.into())
150 }
151}
152
153impl From<LinearGradient> for Fill {
154 fn from(gradient: LinearGradient) -> Self {
155 Fill::LinearGradient(Box::new(gradient))
156 }
157}
158
159impl From<RadialGradient> for Fill {
160 fn from(gradient: RadialGradient) -> Self {
161 Fill::RadialGradient(Box::new(gradient))
162 }
163}
164
165impl From<ConicGradient> for Fill {
166 fn from(gradient: ConicGradient) -> Self {
167 Fill::ConicGradient(Box::new(gradient))
168 }
169}
170
171impl From<ShaderFill> for Fill {
172 fn from(shader: ShaderFill) -> Self {
173 Fill::Shader(Box::new(shader))
174 }
175}
176
177impl fmt::Display for Fill {
178 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
179 match self {
180 Self::Color(color) => color.fmt(f),
181 Self::Shader(shader) => shader.as_ref().fmt(f),
182 Self::LinearGradient(gradient) => gradient.as_ref().fmt(f),
183 Self::RadialGradient(gradient) => gradient.as_ref().fmt(f),
184 Self::ConicGradient(gradient) => gradient.as_ref().fmt(f),
185 }
186 }
187}