use strict_num::PositiveF32;
use crate::{BlendMode, Color, Group, NonEmptyString, NonZeroF32, NonZeroRect, Opacity};
#[derive(Debug)]
pub struct Filter {
pub(crate) id: NonEmptyString,
pub(crate) rect: NonZeroRect,
pub(crate) primitives: Vec<Primitive>,
}
impl Filter {
pub fn id(&self) -> &str {
self.id.get()
}
pub fn rect(&self) -> NonZeroRect {
self.rect
}
pub fn primitives(&self) -> &[Primitive] {
&self.primitives
}
}
#[derive(Clone, Debug)]
pub struct Primitive {
pub(crate) rect: NonZeroRect,
pub(crate) color_interpolation: ColorInterpolation,
pub(crate) result: String,
pub(crate) kind: Kind,
}
impl Primitive {
pub fn rect(&self) -> NonZeroRect {
self.rect
}
pub fn color_interpolation(&self) -> ColorInterpolation {
self.color_interpolation
}
pub fn result(&self) -> &str {
&self.result
}
pub fn kind(&self) -> &Kind {
&self.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(fe) => fe.input1 == *input || fe.input2 == *input,
Kind::ColorMatrix(fe) => fe.input == *input,
Kind::ComponentTransfer(fe) => fe.input == *input,
Kind::Composite(fe) => fe.input1 == *input || fe.input2 == *input,
Kind::ConvolveMatrix(fe) => fe.input == *input,
Kind::DiffuseLighting(fe) => fe.input == *input,
Kind::DisplacementMap(fe) => fe.input1 == *input || fe.input2 == *input,
Kind::DropShadow(fe) => fe.input == *input,
Kind::Flood(_) => false,
Kind::GaussianBlur(fe) => fe.input == *input,
Kind::Image(_) => false,
Kind::Merge(fe) => fe.inputs.iter().any(|i| i == input),
Kind::Morphology(fe) => fe.input == *input,
Kind::Offset(fe) => fe.input == *input,
Kind::SpecularLighting(fe) => fe.input == *input,
Kind::Tile(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, Default)]
pub enum ColorInterpolation {
SRGB,
#[default]
LinearRGB,
}
#[derive(Clone, Debug)]
pub struct Blend {
pub(crate) input1: Input,
pub(crate) input2: Input,
pub(crate) mode: BlendMode,
}
impl Blend {
pub fn input1(&self) -> &Input {
&self.input1
}
pub fn input2(&self) -> &Input {
&self.input2
}
pub fn mode(&self) -> BlendMode {
self.mode
}
}
#[derive(Clone, Debug)]
pub struct ColorMatrix {
pub(crate) input: Input,
pub(crate) kind: ColorMatrixKind,
}
impl ColorMatrix {
pub fn input(&self) -> &Input {
&self.input
}
pub fn kind(&self) -> &ColorMatrixKind {
&self.kind
}
}
#[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(crate) input: Input,
pub(crate) func_r: TransferFunction,
pub(crate) func_g: TransferFunction,
pub(crate) func_b: TransferFunction,
pub(crate) func_a: TransferFunction,
}
impl ComponentTransfer {
pub fn input(&self) -> &Input {
&self.input
}
pub fn func_r(&self) -> &TransferFunction {
&self.func_r
}
pub fn func_g(&self) -> &TransferFunction {
&self.func_g
}
pub fn func_b(&self) -> &TransferFunction {
&self.func_b
}
pub fn func_a(&self) -> &TransferFunction {
&self.func_a
}
}
#[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(crate) input1: Input,
pub(crate) input2: Input,
pub(crate) operator: CompositeOperator,
}
impl Composite {
pub fn input1(&self) -> &Input {
&self.input1
}
pub fn input2(&self) -> &Input {
&self.input2
}
pub fn operator(&self) -> CompositeOperator {
self.operator
}
}
#[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(crate) input: Input,
pub(crate) matrix: ConvolveMatrixData,
pub(crate) divisor: NonZeroF32,
pub(crate) bias: f32,
pub(crate) edge_mode: EdgeMode,
pub(crate) preserve_alpha: bool,
}
impl ConvolveMatrix {
pub fn input(&self) -> &Input {
&self.input
}
pub fn matrix(&self) -> &ConvolveMatrixData {
&self.matrix
}
pub fn divisor(&self) -> NonZeroF32 {
self.divisor
}
pub fn bias(&self) -> f32 {
self.bias
}
pub fn edge_mode(&self) -> EdgeMode {
self.edge_mode
}
pub fn preserve_alpha(&self) -> bool {
self.preserve_alpha
}
}
#[derive(Clone, Debug)]
pub struct ConvolveMatrixData {
pub(crate) target_x: u32,
pub(crate) target_y: u32,
pub(crate) columns: u32,
pub(crate) rows: u32,
pub(crate) data: Vec<f32>,
}
impl ConvolveMatrixData {
pub fn target_x(&self) -> u32 {
self.target_x
}
pub fn target_y(&self) -> u32 {
self.target_y
}
pub fn columns(&self) -> u32 {
self.columns
}
pub fn rows(&self) -> u32 {
self.rows
}
pub fn data(&self) -> &[f32] {
&self.data
}
}
impl ConvolveMatrixData {
pub(crate) 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(crate) input1: Input,
pub(crate) input2: Input,
pub(crate) scale: f32,
pub(crate) x_channel_selector: ColorChannel,
pub(crate) y_channel_selector: ColorChannel,
}
impl DisplacementMap {
pub fn input1(&self) -> &Input {
&self.input1
}
pub fn input2(&self) -> &Input {
&self.input2
}
pub fn scale(&self) -> f32 {
self.scale
}
pub fn x_channel_selector(&self) -> ColorChannel {
self.x_channel_selector
}
pub fn y_channel_selector(&self) -> ColorChannel {
self.y_channel_selector
}
}
#[allow(missing_docs)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ColorChannel {
R,
G,
B,
A,
}
#[derive(Clone, Debug)]
pub struct DropShadow {
pub(crate) input: Input,
pub(crate) dx: f32,
pub(crate) dy: f32,
pub(crate) std_dev_x: PositiveF32,
pub(crate) std_dev_y: PositiveF32,
pub(crate) color: Color,
pub(crate) opacity: Opacity,
}
impl DropShadow {
pub fn input(&self) -> &Input {
&self.input
}
pub fn dx(&self) -> f32 {
self.dx
}
pub fn dy(&self) -> f32 {
self.dy
}
pub fn std_dev_x(&self) -> PositiveF32 {
self.std_dev_x
}
pub fn std_dev_y(&self) -> PositiveF32 {
self.std_dev_y
}
pub fn color(&self) -> Color {
self.color
}
pub fn opacity(&self) -> Opacity {
self.opacity
}
}
#[derive(Clone, Copy, Debug)]
pub struct Flood {
pub(crate) color: Color,
pub(crate) opacity: Opacity,
}
impl Flood {
pub fn color(&self) -> Color {
self.color
}
pub fn opacity(&self) -> Opacity {
self.opacity
}
}
#[derive(Clone, Debug)]
pub struct GaussianBlur {
pub(crate) input: Input,
pub(crate) std_dev_x: PositiveF32,
pub(crate) std_dev_y: PositiveF32,
}
impl GaussianBlur {
pub fn input(&self) -> &Input {
&self.input
}
pub fn std_dev_x(&self) -> PositiveF32 {
self.std_dev_x
}
pub fn std_dev_y(&self) -> PositiveF32 {
self.std_dev_y
}
}
#[derive(Clone, Debug)]
pub struct Image {
pub(crate) root: Group,
}
impl Image {
pub fn root(&self) -> &Group {
&self.root
}
}
#[derive(Clone, Debug)]
pub struct DiffuseLighting {
pub(crate) input: Input,
pub(crate) surface_scale: f32,
pub(crate) diffuse_constant: f32,
pub(crate) lighting_color: Color,
pub(crate) light_source: LightSource,
}
impl DiffuseLighting {
pub fn input(&self) -> &Input {
&self.input
}
pub fn surface_scale(&self) -> f32 {
self.surface_scale
}
pub fn diffuse_constant(&self) -> f32 {
self.diffuse_constant
}
pub fn lighting_color(&self) -> Color {
self.lighting_color
}
pub fn light_source(&self) -> LightSource {
self.light_source
}
}
#[derive(Clone, Debug)]
pub struct SpecularLighting {
pub(crate) input: Input,
pub(crate) surface_scale: f32,
pub(crate) specular_constant: f32,
pub(crate) specular_exponent: f32,
pub(crate) lighting_color: Color,
pub(crate) light_source: LightSource,
}
impl SpecularLighting {
pub fn input(&self) -> &Input {
&self.input
}
pub fn surface_scale(&self) -> f32 {
self.surface_scale
}
pub fn specular_constant(&self) -> f32 {
self.specular_constant
}
pub fn specular_exponent(&self) -> f32 {
self.specular_exponent
}
pub fn lighting_color(&self) -> Color {
self.lighting_color
}
pub fn light_source(&self) -> LightSource {
self.light_source
}
}
#[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(crate) inputs: Vec<Input>,
}
impl Merge {
pub fn inputs(&self) -> &[Input] {
&self.inputs
}
}
#[derive(Clone, Debug)]
pub struct Morphology {
pub(crate) input: Input,
pub(crate) operator: MorphologyOperator,
pub(crate) radius_x: PositiveF32,
pub(crate) radius_y: PositiveF32,
}
impl Morphology {
pub fn input(&self) -> &Input {
&self.input
}
pub fn operator(&self) -> MorphologyOperator {
self.operator
}
pub fn radius_x(&self) -> PositiveF32 {
self.radius_x
}
pub fn radius_y(&self) -> PositiveF32 {
self.radius_y
}
}
#[allow(missing_docs)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum MorphologyOperator {
Erode,
Dilate,
}
#[derive(Clone, Debug)]
pub struct Offset {
pub(crate) input: Input,
pub(crate) dx: f32,
pub(crate) dy: f32,
}
impl Offset {
pub fn input(&self) -> &Input {
&self.input
}
pub fn dx(&self) -> f32 {
self.dx
}
pub fn dy(&self) -> f32 {
self.dy
}
}
#[derive(Clone, Debug)]
pub struct Tile {
pub(crate) input: Input,
}
impl Tile {
pub fn input(&self) -> &Input {
&self.input
}
}
#[derive(Clone, Copy, Debug)]
pub struct Turbulence {
pub(crate) base_frequency_x: PositiveF32,
pub(crate) base_frequency_y: PositiveF32,
pub(crate) num_octaves: u32,
pub(crate) seed: i32,
pub(crate) stitch_tiles: bool,
pub(crate) kind: TurbulenceKind,
}
impl Turbulence {
pub fn base_frequency_x(&self) -> PositiveF32 {
self.base_frequency_x
}
pub fn base_frequency_y(&self) -> PositiveF32 {
self.base_frequency_y
}
pub fn num_octaves(&self) -> u32 {
self.num_octaves
}
pub fn seed(&self) -> i32 {
self.seed
}
pub fn stitch_tiles(&self) -> bool {
self.stitch_tiles
}
pub fn kind(&self) -> TurbulenceKind {
self.kind
}
}
#[allow(missing_docs)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum TurbulenceKind {
FractalNoise,
Turbulence,
}