use crate::common_types::HexColor;
use crate::processed::drawing::shape::path::path_shade_values::PathShadeValues;
use crate::raw::drawing::fill::gradient_fill::{
XlsxGradientFill, XlsxGradientStop, XlsxLinearGradientFill, XlsxPathGradientFill,
};
use crate::raw::drawing::scheme::color_scheme::XlsxColorScheme;
use crate::raw::drawing::st_types::{st_angle_to_degree, st_percentage_to_float};
#[cfg(feature = "serde")]
use serde::Serialize;
use super::fill_rectangle::FillRectangle;
use super::tile_flip::TileFlipValues;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct GradientFill {
pub gradient_stops: Vec<GradientStop>,
pub gradient_type: GradientFillTypeValues,
pub tile_rect: FillRectangle,
pub flip: TileFlipValues,
pub rotate_with_shape: bool,
}
impl GradientFill {
pub(crate) fn from_raw(
raw: Option<XlsxGradientFill>,
color_scheme: Option<XlsxColorScheme>,
ref_color: Option<HexColor>,
) -> Option<Self> {
let Some(raw) = raw else { return None };
let Some(fill_type) = GradientFillTypeValues::from_raw(raw.clone()) else {
return None;
};
let gs: Vec<GradientStop> = raw
.gs_lst
.clone()
.unwrap_or(vec![])
.into_iter()
.map(|s| GradientStop::from_raw(s, color_scheme.clone(), ref_color.clone()))
.collect();
return Some(Self {
gradient_stops: gs,
gradient_type: fill_type,
tile_rect: FillRectangle::from_raw(raw.tile_rect.clone()),
flip: TileFlipValues::from_string(raw.flip.clone()),
rotate_with_shape: raw.rotate_with_shape.clone().unwrap_or(false),
});
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct GradientStop {
pub color: HexColor,
pub position: f64,
}
impl GradientStop {
pub(crate) fn from_raw(
raw: XlsxGradientStop,
color_scheme: Option<XlsxColorScheme>,
ref_color: Option<HexColor>,
) -> Self {
let hex = if let Some(color) = raw.color.clone() {
color.to_hex(color_scheme.clone(), ref_color.clone())
} else {
None
};
return Self {
color: hex.unwrap_or("00000000".to_string()),
position: st_percentage_to_float(raw.pos.clone().unwrap_or(0) as i64),
};
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
pub enum GradientFillTypeValues {
Linear(LinearGradientFill),
Path(PathGradientFill),
}
impl GradientFillTypeValues {
pub(crate) fn from_raw(raw: XlsxGradientFill) -> Option<Self> {
if let Some(lin) = raw.lin.clone() {
return Some(Self::Linear(LinearGradientFill::from_raw(lin)));
};
if let Some(path) = raw.path.clone() {
return Some(Self::Path(PathGradientFill::from_raw(path)));
}
return None;
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct LinearGradientFill {
pub angle: f64,
pub scale_with_fill: bool,
}
impl LinearGradientFill {
pub(crate) fn from_raw(raw: XlsxLinearGradientFill) -> Self {
return Self {
angle: st_angle_to_degree(raw.ang.clone().unwrap_or(0) as i64),
scale_with_fill: raw.scaled.unwrap_or(false),
};
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct PathGradientFill {
pub fill_to_rect: FillRectangle,
pub path: PathShadeValues,
}
impl PathGradientFill {
pub(crate) fn from_raw(raw: XlsxPathGradientFill) -> Self {
return Self {
fill_to_rect: FillRectangle::from_raw(raw.fill_to_rect.clone()),
path: PathShadeValues::from_string(raw.path.clone()),
};
}
}