From 9ae8c2fbd3620f3b9d792aa859de535a24f583c6 Mon Sep 17 00:00:00 2001 From: Schrottkatze Date: Fri, 22 Mar 2024 16:24:04 +0100 Subject: [PATCH] svg-filters: add nice abstractions for component transfer --- crates/svg-filters/src/types/graph.rs | 82 ++++++++++++++++++- crates/svg-filters/src/types/nodes.rs | 44 ++++++++++ .../svg-filters/src/types/nodes/primitives.rs | 21 +++-- .../nodes/primitives/component_transfer.rs | 2 +- 4 files changed, 135 insertions(+), 14 deletions(-) diff --git a/crates/svg-filters/src/types/graph.rs b/crates/svg-filters/src/types/graph.rs index 05d63c3..524ba92 100644 --- a/crates/svg-filters/src/types/graph.rs +++ b/crates/svg-filters/src/types/graph.rs @@ -139,10 +139,12 @@ impl FilterGraph { } pub mod abstracted_inputs { - use petgraph::prelude::NodeIndex; + use petgraph::{data::Build, prelude::NodeIndex}; use crate::{ - types::nodes::primitives::{blend::BlendMode, color_matrix::ColorMatrixType}, + types::nodes::primitives::{ + blend::BlendMode, color_matrix::ColorMatrixType, component_transfer::TransferFn, + }, Node, }; @@ -211,6 +213,82 @@ pub mod abstracted_inputs { .add_edge(self.resolve_input(in2.into()), node_idx, ()); node_idx } + + pub fn component_transfer_rgba( + &mut self, + r#in: impl Into, + r: TransferFn, + g: TransferFn, + b: TransferFn, + a: TransferFn, + ) -> NodeIndex { + let node_idx = self.dag.add_node(Node::component_transfer_rgba(r, g, b, a)); + self.dag + .add_edge(self.resolve_input(r#in.into()), node_idx, ()); + node_idx + } + pub fn component_transfer_rgb( + &mut self, + r#in: impl Into, + r: TransferFn, + g: TransferFn, + b: TransferFn, + ) -> NodeIndex { + let node_idx = self.dag.add_node(Node::component_transfer_rgb(r, g, b)); + self.dag + .add_edge(self.resolve_input(r#in.into()), node_idx, ()); + node_idx + } + pub fn component_transfer_r( + &mut self, + r#in: impl Into, + func: TransferFn, + ) -> NodeIndex { + let node_idx = self.dag.add_node(Node::component_transfer_r(func)); + self.dag + .add_edge(self.resolve_input(r#in.into()), node_idx, ()); + node_idx + } + pub fn component_transfer_g( + &mut self, + r#in: impl Into, + func: TransferFn, + ) -> NodeIndex { + let node_idx = self.dag.add_node(Node::component_transfer_g(func)); + self.dag + .add_edge(self.resolve_input(r#in.into()), node_idx, ()); + node_idx + } + pub fn component_transfer_b( + &mut self, + r#in: impl Into, + func: TransferFn, + ) -> NodeIndex { + let node_idx = self.dag.add_node(Node::component_transfer_b(func)); + self.dag + .add_edge(self.resolve_input(r#in.into()), node_idx, ()); + node_idx + } + pub fn component_transfer_a( + &mut self, + r#in: impl Into, + func: TransferFn, + ) -> NodeIndex { + let node_idx = self.dag.add_node(Node::component_transfer_a(func)); + self.dag + .add_edge(self.resolve_input(r#in.into()), node_idx, ()); + node_idx + } + pub fn component_transfer_single( + &mut self, + r#in: impl Into, + func: TransferFn, + ) -> NodeIndex { + let node_idx = self.dag.add_node(Node::component_transfer_single(func)); + self.dag + .add_edge(self.resolve_input(r#in.into()), node_idx, ()); + node_idx + } } } diff --git a/crates/svg-filters/src/types/nodes.rs b/crates/svg-filters/src/types/nodes.rs index 2edc63b..c9f9334 100644 --- a/crates/svg-filters/src/types/nodes.rs +++ b/crates/svg-filters/src/types/nodes.rs @@ -150,4 +150,48 @@ impl Node { func_a: a, })) } + + pub fn component_transfer_rgb(r: TransferFn, g: TransferFn, b: TransferFn) -> Self { + Self::component_transfer_rgba(r, g, b, TransferFn::Identity) + } + + pub fn component_transfer_r(func: TransferFn) -> Self { + Self::component_transfer_rgba( + func, + TransferFn::Identity, + TransferFn::Identity, + TransferFn::Identity, + ) + } + + pub fn component_transfer_g(func: TransferFn) -> Self { + Self::component_transfer_rgba( + TransferFn::Identity, + func, + TransferFn::Identity, + TransferFn::Identity, + ) + } + + pub fn component_transfer_b(func: TransferFn) -> Self { + Self::component_transfer_rgba( + TransferFn::Identity, + TransferFn::Identity, + func, + TransferFn::Identity, + ) + } + + pub fn component_transfer_a(func: TransferFn) -> Self { + Self::component_transfer_rgba( + TransferFn::Identity, + TransferFn::Identity, + TransferFn::Identity, + func, + ) + } + + pub fn component_transfer_single(func: TransferFn) -> Self { + Self::component_transfer_rgb(func.clone(), func.clone(), func) + } } diff --git a/crates/svg-filters/src/types/nodes/primitives.rs b/crates/svg-filters/src/types/nodes/primitives.rs index 0b6e758..5cdd232 100644 --- a/crates/svg-filters/src/types/nodes/primitives.rs +++ b/crates/svg-filters/src/types/nodes/primitives.rs @@ -1,6 +1,5 @@ -use std::convert::Into; - use quick_xml::{events::attributes::Attribute, ElementWriter, Writer}; +use std::convert::Into; use super::CommonAttrs; @@ -86,18 +85,18 @@ impl WriteElement for FePrimitive { FePrimitive::ColorMatrix(el) => el.attrs(), FePrimitive::ComponentTransfer(el) => el.attrs(), FePrimitive::Composite(el) => el.attrs(), + FePrimitive::GaussianBlur(el) => el.attrs(), + FePrimitive::Offset(el) => el.attrs(), + FePrimitive::Turbulence(el) => el.attrs(), FePrimitive::ConvolveMatrix(_) => todo!(), FePrimitive::DiffuseLighting(_) => todo!(), FePrimitive::DisplacementMap(_) => todo!(), FePrimitive::Flood(_) => todo!(), - FePrimitive::GaussianBlur(el) => el.attrs(), FePrimitive::Image(_) => todo!(), FePrimitive::Merge(_) => todo!(), FePrimitive::Morphology(_) => todo!(), - FePrimitive::Offset(el) => el.attrs(), FePrimitive::SpecularLighting(_) => todo!(), FePrimitive::Tile(_) => todo!(), - FePrimitive::Turbulence(el) => el.attrs(), } } @@ -107,18 +106,18 @@ impl WriteElement for FePrimitive { FePrimitive::ColorMatrix(el) => el.tag_name(), FePrimitive::ComponentTransfer(el) => el.tag_name(), FePrimitive::Composite(el) => el.tag_name(), + FePrimitive::GaussianBlur(el) => el.tag_name(), + FePrimitive::Offset(el) => el.tag_name(), + FePrimitive::Turbulence(el) => el.tag_name(), FePrimitive::ConvolveMatrix(_) => todo!(), FePrimitive::DiffuseLighting(_) => todo!(), FePrimitive::DisplacementMap(_) => todo!(), FePrimitive::Flood(_) => todo!(), - FePrimitive::GaussianBlur(el) => el.tag_name(), FePrimitive::Image(_) => todo!(), FePrimitive::Merge(_) => todo!(), FePrimitive::Morphology(_) => todo!(), - FePrimitive::Offset(el) => el.tag_name(), FePrimitive::SpecularLighting(_) => todo!(), FePrimitive::Tile(_) => todo!(), - FePrimitive::Turbulence(el) => el.tag_name(), } } @@ -134,18 +133,18 @@ impl WriteElement for FePrimitive { FePrimitive::ColorMatrix(el) => el.element_writer(writer, common, inputs, output), FePrimitive::ComponentTransfer(el) => el.element_writer(writer, common, inputs, output), FePrimitive::Composite(el) => el.element_writer(writer, common, inputs, output), + FePrimitive::Turbulence(el) => el.element_writer(writer, common, inputs, output), + FePrimitive::GaussianBlur(el) => el.element_writer(writer, common, inputs, output), + FePrimitive::Offset(el) => el.element_writer(writer, common, inputs, output), FePrimitive::ConvolveMatrix(_) => todo!(), FePrimitive::DiffuseLighting(_) => todo!(), FePrimitive::DisplacementMap(_) => todo!(), FePrimitive::Flood(_) => todo!(), - FePrimitive::GaussianBlur(el) => el.element_writer(writer, common, inputs, output), FePrimitive::Image(_) => todo!(), FePrimitive::Merge(_) => todo!(), FePrimitive::Morphology(_) => todo!(), - FePrimitive::Offset(el) => el.element_writer(writer, common, inputs, output), FePrimitive::SpecularLighting(_) => todo!(), FePrimitive::Tile(_) => todo!(), - FePrimitive::Turbulence(el) => el.element_writer(writer, common, inputs, output), } } } 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 1c37c50..3f8a3a3 100644 --- a/crates/svg-filters/src/types/nodes/primitives/component_transfer.rs +++ b/crates/svg-filters/src/types/nodes/primitives/component_transfer.rs @@ -60,7 +60,7 @@ impl WriteElement for ComponentTransfer { } /// [transfer functions](https://www.w3.org/TR/SVG11/filters.html#transferFuncElements) -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum TransferFn { Identity, Table {