use std::cell::RefCell;
use std::rc::Rc;
use strict_num::PositiveF32;
use svgtypes::AspectRatio;
use crate::{BlendMode, Color, Group, ImageRendering, NonZeroF32, NonZeroRect, Opacity, Units};
#[derive(Clone, Debug)]
pub struct Filter {
pub id: String,
pub units: Units,
pub primitive_units: Units,
pub rect: NonZeroRect,
pub primitives: Vec<Primitive>,
}
pub type SharedFilter = Rc<RefCell<Filter>>;
#[derive(Clone, Debug)]
pub struct Primitive {
pub x: Option<f32>,
pub y: Option<f32>,
pub width: Option<f32>,
pub height: Option<f32>,
pub color_interpolation: ColorInterpolation,
pub result: String,
pub kind: Kind,
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub enum Kind {
Blend(Blend),
ColorMatrix(ColorMatrix),
ComponentTransfer(ComponentTransfer),
Composite(Composite),
ConvolveMatrix(ConvolveMatrix),
DiffuseLighting(DiffuseLighting),
DisplacementMap(DisplacementMap),
DropShadow(DropShadow),
Flood(Flood),
GaussianBlur(GaussianBlur),
Image(Image),
Merge(Merge),
Morphology(Morphology),
Offset(Offset),
SpecularLighting(SpecularLighting),
Tile(Tile),
Turbulence(Turbulence),
}
impl Kind {
pub fn has_input(&self, input: &Input) -> bool {
match self {
Kind::Blend(ref fe) => fe.input1 == *input || fe.input2 == *input,
Kind::ColorMatrix(ref fe) => fe.input == *input,
Kind::ComponentTransfer(ref fe) => fe.input == *input,
Kind::Composite(ref fe) => fe.input1 == *input || fe.input2 == *input,
Kind::ConvolveMatrix(ref fe) => fe.input == *input,
Kind::DiffuseLighting(ref fe) => fe.input == *input,
Kind::DisplacementMap(ref fe) => fe.input1 == *input || fe.input2 == *input,
Kind::DropShadow(ref fe) => fe.input == *input,
Kind::Flood(_) => false,
Kind::GaussianBlur(ref fe) => fe.input == *input,
Kind::Image(_) => false,
Kind::Merge(ref fe) => fe.inputs.iter().any(|i| i == input),
Kind::Morphology(ref fe) => fe.input == *input,
Kind::Offset(ref fe) => fe.input == *input,
Kind::SpecularLighting(ref fe) => fe.input == *input,
Kind::Tile(ref fe) => fe.input == *input,
Kind::Turbulence(_) => false,
}
}
}
#[allow(missing_docs)]
#[derive(Clone, PartialEq, Debug)]
pub enum Input {
SourceGraphic,
SourceAlpha,
Reference(String),
}
#[allow(missing_docs)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ColorInterpolation {
SRGB,
LinearRGB,
}
impl Default for ColorInterpolation {
fn default() -> Self {
ColorInterpolation::LinearRGB
}
}
#[derive(Clone, Debug)]
pub struct Blend {
pub input1: Input,
pub input2: Input,
pub mode: BlendMode,
}
#[derive(Clone, Debug)]
pub struct ColorMatrix {
pub input: Input,
pub kind: ColorMatrixKind,
}
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub enum ColorMatrixKind {
Matrix(Vec<f32>), Saturate(PositiveF32),
HueRotate(f32),
LuminanceToAlpha,
}
impl Default for ColorMatrixKind {
fn default() -> Self {
ColorMatrixKind::Matrix(vec![
1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0,
])
}
}
#[derive(Clone, Debug)]
pub struct ComponentTransfer {
pub input: Input,
pub func_r: TransferFunction,
pub func_g: TransferFunction,
pub func_b: TransferFunction,
pub func_a: TransferFunction,
}
#[derive(Clone, Debug)]
pub enum TransferFunction {
Identity,
Table(Vec<f32>),
Discrete(Vec<f32>),
#[allow(missing_docs)]
Linear { slope: f32, intercept: f32 },
#[allow(missing_docs)]
Gamma {
amplitude: f32,
exponent: f32,
offset: f32,
},
}
#[derive(Clone, Debug)]
pub struct Composite {
pub input1: Input,
pub input2: Input,
pub operator: CompositeOperator,
}
#[allow(missing_docs)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum CompositeOperator {
Over,
In,
Out,
Atop,
Xor,
Arithmetic { k1: f32, k2: f32, k3: f32, k4: f32 },
}
#[derive(Clone, Debug)]
pub struct ConvolveMatrix {
pub input: Input,
pub matrix: ConvolveMatrixData,
pub divisor: NonZeroF32,
pub bias: f32,
pub edge_mode: EdgeMode,
pub preserve_alpha: bool,
}
#[derive(Clone, Debug)]
pub struct ConvolveMatrixData {
pub target_x: u32,
pub target_y: u32,
pub columns: u32,
pub rows: u32,
pub data: Vec<f32>,
}
impl ConvolveMatrixData {
pub fn new(
target_x: u32,
target_y: u32,
columns: u32,
rows: u32,
data: Vec<f32>,
) -> Option<Self> {
if (columns * rows) as usize != data.len() || target_x >= columns || target_y >= rows {
return None;
}
Some(ConvolveMatrixData {
target_x,
target_y,
columns,
rows,
data,
})
}
pub fn get(&self, x: u32, y: u32) -> f32 {
self.data[(y * self.columns + x) as usize]
}
}
#[allow(missing_docs)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum EdgeMode {
None,
Duplicate,
Wrap,
}
#[derive(Clone, Debug)]
pub struct DisplacementMap {
pub input1: Input,
pub input2: Input,
pub scale: f32,
pub x_channel_selector: ColorChannel,
pub y_channel_selector: ColorChannel,
}
#[allow(missing_docs)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ColorChannel {
R,
G,
B,
A,
}
#[derive(Clone, Debug)]
pub struct DropShadow {
pub input: Input,
pub dx: f32,
pub dy: f32,
pub std_dev_x: PositiveF32,
pub std_dev_y: PositiveF32,
pub color: Color,
pub opacity: Opacity,
}
#[derive(Clone, Copy, Debug)]
pub struct Flood {
pub color: Color,
pub opacity: Opacity,
}
#[derive(Clone, Debug)]
pub struct GaussianBlur {
pub input: Input,
pub std_dev_x: PositiveF32,
pub std_dev_y: PositiveF32,
}
#[derive(Clone, Debug)]
pub struct Image {
pub aspect: AspectRatio,
pub rendering_mode: ImageRendering,
pub data: ImageKind,
}
#[derive(Clone, Debug)]
pub enum ImageKind {
Image(crate::ImageKind),
Use(Box<Group>),
}
#[derive(Clone, Debug)]
pub struct DiffuseLighting {
pub input: Input,
pub surface_scale: f32,
pub diffuse_constant: f32,
pub lighting_color: Color,
pub light_source: LightSource,
}
#[derive(Clone, Debug)]
pub struct SpecularLighting {
pub input: Input,
pub surface_scale: f32,
pub specular_constant: f32,
pub specular_exponent: f32,
pub lighting_color: Color,
pub light_source: LightSource,
}
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub enum LightSource {
DistantLight(DistantLight),
PointLight(PointLight),
SpotLight(SpotLight),
}
#[derive(Clone, Copy, Debug)]
pub struct DistantLight {
pub azimuth: f32,
pub elevation: f32,
}
#[derive(Clone, Copy, Debug)]
pub struct PointLight {
pub x: f32,
pub y: f32,
pub z: f32,
}
#[derive(Clone, Copy, Debug)]
pub struct SpotLight {
pub x: f32,
pub y: f32,
pub z: f32,
pub points_at_x: f32,
pub points_at_y: f32,
pub points_at_z: f32,
pub specular_exponent: PositiveF32,
pub limiting_cone_angle: Option<f32>,
}
#[derive(Clone, Debug)]
pub struct Merge {
pub inputs: Vec<Input>,
}
#[derive(Clone, Debug)]
pub struct Morphology {
pub input: Input,
pub operator: MorphologyOperator,
pub radius_x: PositiveF32,
pub radius_y: PositiveF32,
}
#[allow(missing_docs)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum MorphologyOperator {
Erode,
Dilate,
}
#[derive(Clone, Debug)]
pub struct Offset {
pub input: Input,
pub dx: f32,
pub dy: f32,
}
#[derive(Clone, Debug)]
pub struct Tile {
pub input: Input,
}
#[derive(Clone, Copy, Debug)]
pub struct Turbulence {
pub base_frequency_x: PositiveF32,
pub base_frequency_y: PositiveF32,
pub num_octaves: u32,
pub seed: i32,
pub stitch_tiles: bool,
pub kind: TurbulenceKind,
}
#[allow(missing_docs)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum TurbulenceKind {
FractalNoise,
Turbulence,
}