From 56848a1b059da24f09855a027ac101693b83086c Mon Sep 17 00:00:00 2001 From: Schrottkatze Date: Fri, 15 Mar 2024 19:52:40 +0100 Subject: [PATCH] svg-filters: add basic graph and stuffs --- Cargo.toml | 3 +- crates/app/Cargo.toml | 1 + crates/svg-filters/src/lib.rs | 17 +-- crates/svg-filters/src/main.rs | 54 +++++++++ crates/svg-filters/src/types.rs | 70 ++++++++++- crates/svg-filters/src/types/length.rs | 3 + crates/svg-filters/src/types/nodes.rs | 112 +++++++++++++++++- .../svg-filters/src/types/nodes/primitives.rs | 47 ++++---- .../src/types/nodes/primitives/blend.rs | 20 +++- .../types/nodes/primitives/color_matrix.rs | 24 ++-- .../nodes/primitives/component_transfer.rs | 2 + .../src/types/nodes/primitives/composite.rs | 16 ++- .../types/nodes/primitives/convolve_matrix.rs | 2 + .../nodes/primitives/diffuse_lighting.rs | 1 + .../nodes/primitives/displacement_map.rs | 2 + .../src/types/nodes/primitives/flood.rs | 1 + .../types/nodes/primitives/gaussian_blur.rs | 17 ++- .../src/types/nodes/primitives/image.rs | 1 + .../src/types/nodes/primitives/merge.rs | 1 + .../src/types/nodes/primitives/morphology.rs | 2 + .../src/types/nodes/primitives/offset.rs | 7 ++ .../nodes/primitives/specular_lighting.rs | 1 + .../src/types/nodes/primitives/tile.rs | 1 + .../src/types/nodes/primitives/turbulence.rs | 3 + .../src/types/nodes/standard_input.rs | 1 + 25 files changed, 340 insertions(+), 69 deletions(-) create mode 100644 crates/svg-filters/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 2ca8bdc..cbd514c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,8 @@ members = [ "crates/app", "crates/eval", "crates/ir", - "crates/lang", "crates/svg-filters", + "crates/lang", + "crates/svg-filters", ] resolver = "2" diff --git a/crates/app/Cargo.toml b/crates/app/Cargo.toml index 2caaaf4..10182c2 100644 --- a/crates/app/Cargo.toml +++ b/crates/app/Cargo.toml @@ -2,6 +2,7 @@ name = "app" version = "0.1.0" edition = "2021" +default-run = "app" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/crates/svg-filters/src/lib.rs b/crates/svg-filters/src/lib.rs index 11b6708..5081a19 100644 --- a/crates/svg-filters/src/lib.rs +++ b/crates/svg-filters/src/lib.rs @@ -1,16 +1,5 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right -} - pub mod types; -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} +pub use types::nodes::Node; +pub use types::Edge; +pub use types::Filter; diff --git a/crates/svg-filters/src/main.rs b/crates/svg-filters/src/main.rs new file mode 100644 index 0000000..d628d3e --- /dev/null +++ b/crates/svg-filters/src/main.rs @@ -0,0 +1,54 @@ +use svg_filters::{types::nodes::primitives::color_matrix::ColorMatrixType, Edge, Filter, Node}; + +fn main() { + let mut filter = Filter::new(); + + // + // + // + // + + // + + // + // + // + + // + // + // + + let chan_r = filter.add_node(Node::color_matrix(ColorMatrixType::Matrix(Box::new([ + 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., + ])))); + let chan_g = filter.add_node(Node::color_matrix(ColorMatrixType::Matrix(Box::new([ + 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., + ])))); + let chan_b = filter.add_node(Node::color_matrix(ColorMatrixType::Matrix(Box::new([ + 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 1., 0., + ])))); + + let offset_r = filter.add_node(Node::offset(25., 0.)); + let offset_b = filter.add_node(Node::offset(-25., 0.)); + let blur_r = filter.add_node(Node::gaussian_blur_xy(5, 0)); + let blur_b = filter.add_node(Node::gaussian_blur_xy(5, 0)); + + let composite_rb = filter.add_node(Node::composite_arithmetic(0., 1., 1., 0.)); + let composite_final = filter.add_node(Node::composite_arithmetic(0., 1., 1., 0.)); + + filter.graph.extend_with_edges(&[ + (filter.source_graphic(), chan_r, Edge::new()), + (filter.source_graphic(), chan_b, Edge::new()), + (filter.source_graphic(), chan_g, Edge::new()), + (chan_r, offset_r, Edge::new()), + (offset_r, blur_r, Edge::new()), + (chan_b, offset_b, Edge::new()), + (offset_b, blur_b, Edge::new()), + (blur_r, composite_rb, Edge::in_idx(0)), + (blur_b, composite_rb, Edge::in_idx(1)), + (composite_rb, composite_final, Edge::in_idx(0)), + (chan_g, composite_final, Edge::in_idx(1)), + ]); + + println!("{filter:#?}") +} diff --git a/crates/svg-filters/src/types.rs b/crates/svg-filters/src/types.rs index 94ecb4b..31e0954 100644 --- a/crates/svg-filters/src/types.rs +++ b/crates/svg-filters/src/types.rs @@ -1,20 +1,80 @@ use std::collections::HashMap; -use petgraph::graphmap::DiGraphMap; +use petgraph::{ + adj::EdgeIndex, data::Build, graph::DiGraph, graphmap::DiGraphMap, prelude::NodeIndex, +}; pub mod length; pub mod nodes; +use crate::types::nodes::primitives::color_matrix::{ColorMatrix, ColorMatrixType}; + use self::{ length::{Coordinate, Length}, nodes::Node, }; +#[derive(Debug)] pub struct Filter<'a> { - graph: DiGraphMap, + pub graph: DiGraph>, + source_graphic_idx: NodeIndex, } -pub enum Edge<'a> { - Named(&'a str, u8), + +impl Filter<'_> { + pub fn new() -> Self { + let mut graph = DiGraph::new(); + let source_graphic_idx = graph.add_node(Node::StdInput( + nodes::standard_input::StandardInput::SourceGraphic, + )); + + Self { + graph, + source_graphic_idx, + } + } + + pub fn add_node(&mut self, node: Node) -> NodeIndex { + self.graph.add_node(node) + } + + pub fn source_graphic(&self) -> NodeIndex { + self.source_graphic_idx + } +} + +impl Default for Filter<'_> { + fn default() -> Self { + Self::new() + } +} + +#[derive(Debug, Clone)] +pub struct Edge<'a> { + edge_type: EdgeType<'a>, + /// the index of the `in` attribute on the target element + /// if None, just `in` + in_idx: Option, +} + +impl Edge<'_> { + pub fn new() -> Self { + Self { + edge_type: EdgeType::Unnamed, + in_idx: None, + } + } + + pub fn in_idx(idx: u8) -> Self { + Self { + edge_type: EdgeType::Unnamed, + in_idx: Some(idx), + } + } +} + +#[derive(Debug, Clone)] +pub enum EdgeType<'a> { + Named(&'a str), /// For standard inputs such as SourceGraphic etc., which we'll just be representing as nodes for simplicity - Unnamed(u8), + Unnamed, } diff --git a/crates/svg-filters/src/types/length.rs b/crates/svg-filters/src/types/length.rs index 4db3fd9..1186181 100644 --- a/crates/svg-filters/src/types/length.rs +++ b/crates/svg-filters/src/types/length.rs @@ -1,7 +1,10 @@ +#[derive(Default, Debug)] pub struct Length(f32, Unit); pub type Coordinate = Length; +#[derive(Default, Debug)] pub enum Unit { + #[default] None, Em, Ex, diff --git a/crates/svg-filters/src/types/nodes.rs b/crates/svg-filters/src/types/nodes.rs index 3571e76..29982bc 100644 --- a/crates/svg-filters/src/types/nodes.rs +++ b/crates/svg-filters/src/types/nodes.rs @@ -1,13 +1,113 @@ -use self::{primitives::Primitive, standard_input::StandardInput}; +use self::{ + primitives::{ + blend::{Blend, BlendMode}, + color_matrix::{ColorMatrix, ColorMatrixType}, + composite::{Composite, CompositeOperator}, + gaussian_blur::GaussianBlur, + offset::Offset, + FePrimitive, + }, + standard_input::StandardInput, +}; use super::length::{Coordinate, Length}; +pub mod primitives; pub mod standard_input; -pub mod primitives; - +#[derive(Debug)] pub enum Node { - /// We represent those as Nodes because they're essentially magical nodes - StandardInput(StandardInput), - Primitive(Primitive), + StdInput(StandardInput), + Primitive { + primitive: FePrimitive, + common_attrs: CommonAttrs, + }, +} + +impl Default for Node { + fn default() -> Self { + Self::StdInput(StandardInput::SourceGraphic) + } +} + +#[derive(Default, Debug)] +struct CommonAttrs { + x: Coordinate, + y: Coordinate, + width: Length, + height: Length, +} + +impl Node { + pub fn simple(el: FePrimitive) -> Node { + Node::Primitive { + primitive: el, + common_attrs: CommonAttrs::default(), + } + } + + pub fn input_count(&self) -> u8 { + match self { + Node::Primitive { + primitive: + FePrimitive::ColorMatrix(_) + | FePrimitive::ComponentTransfer(_) + | FePrimitive::ConvolveMatrix(_) + | FePrimitive::DiffuseLighting(_) + | FePrimitive::GaussianBlur(_) + | FePrimitive::Morphology(_) + | FePrimitive::Offset(_) + | FePrimitive::SpecularLighting(_) + | FePrimitive::Tile(_), + .. + } => 1, + + Node::Primitive { + primitive: + FePrimitive::Composite(_) | FePrimitive::Blend(_) | FePrimitive::DisplacementMap(_), + .. + } => 2, + + Node::StdInput(_) + | Node::Primitive { + primitive: + FePrimitive::Flood(_) | FePrimitive::Image(_) | FePrimitive::Turbulence(_), + .. + } => 0, + Node::Primitive { + primitive: FePrimitive::Merge(_), + .. + } => todo!(), + } + } + + pub fn blend(mode: BlendMode) -> Self { + Self::simple(FePrimitive::Blend(Blend::new(mode))) + } + + pub fn color_matrix(cm_type: ColorMatrixType) -> Self { + Self::simple(FePrimitive::ColorMatrix(ColorMatrix::new(cm_type))) + } + + pub fn composite(op: CompositeOperator) -> Self { + Self::simple(FePrimitive::Composite(Composite::new(op))) + } + + pub fn composite_arithmetic(k1: f32, k2: f32, k3: f32, k4: f32) -> Self { + Self::simple(FePrimitive::Composite(Composite::arithmetic( + k1, k2, k3, k4, + ))) + } + + pub fn gaussian_blur(v: u16) -> Self { + Self::simple(FePrimitive::GaussianBlur(GaussianBlur::single(v))) + } + + pub fn gaussian_blur_xy(x: u16, y: u16) -> Self { + Self::simple(FePrimitive::GaussianBlur(GaussianBlur::with_xy(x, y))) + } + + pub fn offset(dx: f32, dy: f32) -> Self { + Self::simple(FePrimitive::Offset(Offset::new(dx, dy))) + } } diff --git a/crates/svg-filters/src/types/nodes/primitives.rs b/crates/svg-filters/src/types/nodes/primitives.rs index 433f190..6be79b3 100644 --- a/crates/svg-filters/src/types/nodes/primitives.rs +++ b/crates/svg-filters/src/types/nodes/primitives.rs @@ -1,36 +1,29 @@ use crate::types::length::{Coordinate, Length}; -mod blend; -mod color_matrix; -mod component_transfer; -mod composite; -mod convolve_matrix; -mod diffuse_lighting; -mod displacement_map; -mod flood; -mod gaussian_blur; -mod image; -mod merge; -mod morphology; -mod offset; -mod specular_lighting; -mod tile; -mod turbulence; +use self::blend::BlendMode; -pub struct Primitive { - primitive: FePrimitive, - common_attrs: CommonAttrs, -} +use super::Node; -struct CommonAttrs { - x: Coordinate, - y: Coordinate, - width: Length, - height: Length, -} +pub mod blend; +pub mod color_matrix; +pub mod component_transfer; +pub mod composite; +pub mod convolve_matrix; +pub mod diffuse_lighting; +pub mod displacement_map; +pub mod flood; +pub mod gaussian_blur; +pub mod image; +pub mod merge; +pub mod morphology; +pub mod offset; +pub mod specular_lighting; +pub mod tile; +pub mod turbulence; /// svg filter effects primitives -enum FePrimitive { +#[derive(Debug)] +pub enum FePrimitive { // 2 inputs Blend(blend::Blend), ColorMatrix(color_matrix::ColorMatrix), diff --git a/crates/svg-filters/src/types/nodes/primitives/blend.rs b/crates/svg-filters/src/types/nodes/primitives/blend.rs index c8972de..242f763 100644 --- a/crates/svg-filters/src/types/nodes/primitives/blend.rs +++ b/crates/svg-filters/src/types/nodes/primitives/blend.rs @@ -1,10 +1,26 @@ /// [feBlend](https://www.w3.org/TR/SVG11/filters.html#feBlendElement) -pub struct Blend { +#[derive(Debug)] +pub(in crate::types::nodes) struct Blend { mode: BlendMode, } +impl Blend { + pub fn new(mode: BlendMode) -> Self { + Self { mode } + } +} + +impl Default for Blend { + fn default() -> Self { + Self { + mode: BlendMode::Normal, + } + } +} + /// as according to https://drafts.fxtf.org/compositing-1/#blending -enum BlendMode { +#[derive(Debug)] +pub enum BlendMode { Normal, Multiply, Screen, diff --git a/crates/svg-filters/src/types/nodes/primitives/color_matrix.rs b/crates/svg-filters/src/types/nodes/primitives/color_matrix.rs index bdc945e..fbae6b2 100644 --- a/crates/svg-filters/src/types/nodes/primitives/color_matrix.rs +++ b/crates/svg-filters/src/types/nodes/primitives/color_matrix.rs @@ -1,19 +1,19 @@ /// [feColorMatrix](https://www.w3.org/TR/SVG11/filters.html#feColorMatrixElement) +#[derive(Debug)] pub struct ColorMatrix { cm_type: ColorMatrixType, } -enum ColorMatrixType { - Matrix { - values: [f32; 20], - }, - Saturate { - // is the values attribute anyway tho - value: f32, - }, - HueRotate { - // also the values attribute - degrees: f32, - }, +impl ColorMatrix { + pub fn new(cm_type: ColorMatrixType) -> Self { + Self { cm_type } + } +} + +#[derive(Debug)] +pub enum ColorMatrixType { + Matrix(Box<[f32; 20]>), + Saturate(f32), + HueRotate(f32), LuminanceToAlpha, } diff --git a/crates/svg-filters/src/types/nodes/primitives/component_transfer.rs b/crates/svg-filters/src/types/nodes/primitives/component_transfer.rs index 6c58d87..3ccc039 100644 --- a/crates/svg-filters/src/types/nodes/primitives/component_transfer.rs +++ b/crates/svg-filters/src/types/nodes/primitives/component_transfer.rs @@ -1,4 +1,5 @@ /// [feComponentTransfer](https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement) +#[derive(Debug)] pub struct ComponentTransfer { func_r: TransferFunction, func_g: TransferFunction, @@ -7,6 +8,7 @@ pub struct ComponentTransfer { } /// [transfer functions](https://www.w3.org/TR/SVG11/filters.html#transferFuncElements) +#[derive(Debug)] enum TransferFunction { Identity, Table { diff --git a/crates/svg-filters/src/types/nodes/primitives/composite.rs b/crates/svg-filters/src/types/nodes/primitives/composite.rs index ae95447..c86de26 100644 --- a/crates/svg-filters/src/types/nodes/primitives/composite.rs +++ b/crates/svg-filters/src/types/nodes/primitives/composite.rs @@ -1,9 +1,23 @@ /// [feComposite](https://www.w3.org/TR/SVG11/filters.html#feCompositeElement) +#[derive(Debug)] pub struct Composite { operator: CompositeOperator, } -enum CompositeOperator { +impl Composite { + pub fn new(op: CompositeOperator) -> Self { + Self { operator: op } + } + + pub fn arithmetic(k1: f32, k2: f32, k3: f32, k4: f32) -> Self { + Self { + operator: CompositeOperator::Arithmetic { k1, k2, k3, k4 }, + } + } +} + +#[derive(Debug)] +pub enum CompositeOperator { Over, In, Out, diff --git a/crates/svg-filters/src/types/nodes/primitives/convolve_matrix.rs b/crates/svg-filters/src/types/nodes/primitives/convolve_matrix.rs index a619ac9..1fe2ef4 100644 --- a/crates/svg-filters/src/types/nodes/primitives/convolve_matrix.rs +++ b/crates/svg-filters/src/types/nodes/primitives/convolve_matrix.rs @@ -1,3 +1,4 @@ +#[derive(Debug)] pub struct ConvolveMatrix { order: (u16, u16), // must be checked to be `order.0 * order.1` @@ -11,6 +12,7 @@ pub struct ConvolveMatrix { preserve_alpha: bool, } +#[derive(Debug)] enum EdgeMode { None, Duplicate, diff --git a/crates/svg-filters/src/types/nodes/primitives/diffuse_lighting.rs b/crates/svg-filters/src/types/nodes/primitives/diffuse_lighting.rs index 18a0485..5d9cd6f 100644 --- a/crates/svg-filters/src/types/nodes/primitives/diffuse_lighting.rs +++ b/crates/svg-filters/src/types/nodes/primitives/diffuse_lighting.rs @@ -1,2 +1,3 @@ // TODO +#[derive(Debug)] pub struct DiffuseLighting; diff --git a/crates/svg-filters/src/types/nodes/primitives/displacement_map.rs b/crates/svg-filters/src/types/nodes/primitives/displacement_map.rs index e59a520..b6485ac 100644 --- a/crates/svg-filters/src/types/nodes/primitives/displacement_map.rs +++ b/crates/svg-filters/src/types/nodes/primitives/displacement_map.rs @@ -1,10 +1,12 @@ /// [feDisplacementMap](https://www.w3.org/TR/SVG11/filters.html#feDisplacementMapElement) +#[derive(Debug)] pub struct DisplacementMap { scale: f32, x_channel_selector: Channel, y_channel_selector: Channel, } +#[derive(Debug)] enum Channel { A, R, diff --git a/crates/svg-filters/src/types/nodes/primitives/flood.rs b/crates/svg-filters/src/types/nodes/primitives/flood.rs index 6858c71..94f6eee 100644 --- a/crates/svg-filters/src/types/nodes/primitives/flood.rs +++ b/crates/svg-filters/src/types/nodes/primitives/flood.rs @@ -1,6 +1,7 @@ use csscolorparser::Color; /// [feFlood](https://www.w3.org/TR/SVG11/filters.html#feFloodElement) +#[derive(Debug)] pub struct Flood { flood_color: Color, flood_opacity: f32, diff --git a/crates/svg-filters/src/types/nodes/primitives/gaussian_blur.rs b/crates/svg-filters/src/types/nodes/primitives/gaussian_blur.rs index 5ad8047..e6ca9c1 100644 --- a/crates/svg-filters/src/types/nodes/primitives/gaussian_blur.rs +++ b/crates/svg-filters/src/types/nodes/primitives/gaussian_blur.rs @@ -1,4 +1,19 @@ /// [feGaussianBlur](https://www.w3.org/TR/SVG11/filters.html#feGaussianBlurElement) +#[derive(Debug)] pub struct GaussianBlur { - std_deviation: (f32, f32), + std_deviation: (u16, u16), +} + +impl GaussianBlur { + pub fn single(v: u16) -> Self { + Self { + std_deviation: (v, v), + } + } + + pub fn with_xy(x: u16, y: u16) -> Self { + Self { + std_deviation: (x, y), + } + } } diff --git a/crates/svg-filters/src/types/nodes/primitives/image.rs b/crates/svg-filters/src/types/nodes/primitives/image.rs index d068c89..c52c0b7 100644 --- a/crates/svg-filters/src/types/nodes/primitives/image.rs +++ b/crates/svg-filters/src/types/nodes/primitives/image.rs @@ -1,2 +1,3 @@ // TODO +#[derive(Debug)] pub struct Image; diff --git a/crates/svg-filters/src/types/nodes/primitives/merge.rs b/crates/svg-filters/src/types/nodes/primitives/merge.rs index a65df6e..ab26374 100644 --- a/crates/svg-filters/src/types/nodes/primitives/merge.rs +++ b/crates/svg-filters/src/types/nodes/primitives/merge.rs @@ -1,2 +1,3 @@ // TODO +#[derive(Debug)] pub struct Merge; diff --git a/crates/svg-filters/src/types/nodes/primitives/morphology.rs b/crates/svg-filters/src/types/nodes/primitives/morphology.rs index 6fd50e1..6b33825 100644 --- a/crates/svg-filters/src/types/nodes/primitives/morphology.rs +++ b/crates/svg-filters/src/types/nodes/primitives/morphology.rs @@ -1,9 +1,11 @@ /// [feMorphology](https://www.w3.org/TR/SVG11/filters.html#feMorphologyElement) +#[derive(Debug)] pub struct Morphology { operator: Operator, radius: (f32, f32), } +#[derive(Debug)] enum Operator { Erode, Dilate, diff --git a/crates/svg-filters/src/types/nodes/primitives/offset.rs b/crates/svg-filters/src/types/nodes/primitives/offset.rs index 1473b0e..96b47ef 100644 --- a/crates/svg-filters/src/types/nodes/primitives/offset.rs +++ b/crates/svg-filters/src/types/nodes/primitives/offset.rs @@ -1,5 +1,12 @@ /// [feOffset](https://www.w3.org/TR/SVG11/filters.html#feOffsetElement) +#[derive(Debug)] pub struct Offset { dx: f32, dy: f32, } + +impl Offset { + pub fn new(dx: f32, dy: f32) -> Self { + Self { dx, dy } + } +} diff --git a/crates/svg-filters/src/types/nodes/primitives/specular_lighting.rs b/crates/svg-filters/src/types/nodes/primitives/specular_lighting.rs index ab41f49..16a6fcc 100644 --- a/crates/svg-filters/src/types/nodes/primitives/specular_lighting.rs +++ b/crates/svg-filters/src/types/nodes/primitives/specular_lighting.rs @@ -1,2 +1,3 @@ // TODO +#[derive(Debug)] pub struct SpecularLighting; diff --git a/crates/svg-filters/src/types/nodes/primitives/tile.rs b/crates/svg-filters/src/types/nodes/primitives/tile.rs index b943271..7a957c5 100644 --- a/crates/svg-filters/src/types/nodes/primitives/tile.rs +++ b/crates/svg-filters/src/types/nodes/primitives/tile.rs @@ -1,2 +1,3 @@ /// [feTile](https://www.w3.org/TR/SVG11/filters.html#feTileElement) +#[derive(Debug)] pub struct Tile; diff --git a/crates/svg-filters/src/types/nodes/primitives/turbulence.rs b/crates/svg-filters/src/types/nodes/primitives/turbulence.rs index 998b472..ec815cb 100644 --- a/crates/svg-filters/src/types/nodes/primitives/turbulence.rs +++ b/crates/svg-filters/src/types/nodes/primitives/turbulence.rs @@ -1,4 +1,5 @@ /// [feTurbulence](https://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement) +#[derive(Debug)] pub struct Turbulence { base_frequency: (f32, f32), num_octaves: (u16), @@ -8,10 +9,12 @@ pub struct Turbulence { noise_type: NoiseType, } +#[derive(Debug)] enum StitchTiles { Stitch, NoStitch, } +#[derive(Debug)] enum NoiseType { Turbulence, FractalNoise, diff --git a/crates/svg-filters/src/types/nodes/standard_input.rs b/crates/svg-filters/src/types/nodes/standard_input.rs index e1ae7d1..add10d0 100644 --- a/crates/svg-filters/src/types/nodes/standard_input.rs +++ b/crates/svg-filters/src/types/nodes/standard_input.rs @@ -1,5 +1,6 @@ /// [svg filter effect standard input](https://www.w3.org/TR/SVG11/filters.html#FilterPrimitiveInAttribute) /// technically not a node, but for implementation simplicity... yeah +#[derive(Debug)] pub enum StandardInput { SourceGraphic, SourceAlpha,