mod gradient;
mod linear_gradient;
mod pattern;
mod radial_gradient;
mod sweep_gradient;
use tiny_skia_path::{NormalizedF32, Scalar};
pub use gradient::GradientStop;
pub use linear_gradient::LinearGradient;
pub use pattern::{FilterQuality, Pattern, PixmapPaint};
pub use radial_gradient::RadialGradient;
pub use sweep_gradient::SweepGradient;
use crate::{Color, ColorSpace, Transform};
use crate::pipeline::RasterPipelineBuilder;
#[derive(Copy, Clone, Default, PartialEq, Debug)]
pub enum SpreadMode {
#[default]
Pad,
Reflect,
Repeat,
}
#[derive(Clone, PartialEq, Debug)]
pub enum Shader<'a> {
SolidColor(Color),
LinearGradient(LinearGradient),
RadialGradient(RadialGradient),
SweepGradient(SweepGradient),
Pattern(Pattern<'a>),
}
impl Shader<'_> {
pub fn is_opaque(&self) -> bool {
match self {
Shader::SolidColor(c) => c.is_opaque(),
Shader::LinearGradient(g) => g.is_opaque(),
Shader::RadialGradient(_) => false,
Shader::SweepGradient(g) => g.is_opaque(),
Shader::Pattern(_) => false,
}
}
#[must_use]
pub(crate) fn push_stages(&self, cs: ColorSpace, p: &mut RasterPipelineBuilder) -> bool {
match self {
Shader::SolidColor(color) => {
let color = cs.expand_color(*color).premultiply();
p.push_uniform_color(color);
true
}
Shader::LinearGradient(g) => g.push_stages(cs, p),
Shader::RadialGradient(g) => g.push_stages(cs, p),
Shader::SweepGradient(g) => g.push_stages(cs, p),
Shader::Pattern(patt) => patt.push_stages(cs, p),
}
}
pub fn transform(&mut self, ts: Transform) {
match self {
Shader::SolidColor(_) => {}
Shader::LinearGradient(g) => {
g.base.transform = g.base.transform.post_concat(ts);
}
Shader::RadialGradient(g) => {
g.base.transform = g.base.transform.post_concat(ts);
}
Shader::SweepGradient(g) => {
g.base.transform = g.base.transform.post_concat(ts);
}
Shader::Pattern(p) => {
p.transform = p.transform.post_concat(ts);
}
}
}
pub fn apply_opacity(&mut self, opacity: f32) {
match self {
Shader::SolidColor(ref mut c) => {
c.apply_opacity(opacity);
}
Shader::LinearGradient(g) => {
g.base.apply_opacity(opacity);
}
Shader::RadialGradient(g) => {
g.base.apply_opacity(opacity);
}
Shader::SweepGradient(g) => {
g.base.apply_opacity(opacity);
}
Shader::Pattern(ref mut p) => {
p.opacity = NormalizedF32::new(p.opacity.get() * opacity.bound(0.0, 1.0)).unwrap();
}
}
}
}