mod gradient;
mod linear_gradient;
mod pattern;
mod radial_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;
use crate::{Color, Transform};
use crate::pipeline::RasterPipelineBuilder;
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum SpreadMode {
Pad,
Reflect,
Repeat,
}
impl Default for SpreadMode {
fn default() -> Self {
SpreadMode::Pad
}
}
#[derive(Clone, Debug)]
pub enum Shader<'a> {
SolidColor(Color),
LinearGradient(LinearGradient),
RadialGradient(RadialGradient),
Pattern(Pattern<'a>),
}
impl<'a> Shader<'a> {
pub fn is_opaque(&self) -> bool {
match self {
Shader::SolidColor(ref c) => c.is_opaque(),
Shader::LinearGradient(ref g) => g.is_opaque(),
Shader::RadialGradient(_) => false,
Shader::Pattern(_) => false,
}
}
pub(crate) fn push_stages(&self, p: &mut RasterPipelineBuilder) -> Option<()> {
match self {
Shader::SolidColor(color) => {
p.push_uniform_color(color.premultiply());
Some(())
}
Shader::LinearGradient(ref g) => g.push_stages(p),
Shader::RadialGradient(ref g) => g.push_stages(p),
Shader::Pattern(ref patt) => patt.push_stages(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::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::Pattern(ref mut p) => {
p.opacity = NormalizedF32::new(p.opacity.get() * opacity.bound(0.0, 1.0)).unwrap();
}
}
}
}