From dc7d76dc264dd0446c4c0eb85da240faa5f79916 Mon Sep 17 00:00:00 2001 From: Schrottkatze Date: Tue, 19 Mar 2024 15:47:09 +0100 Subject: [PATCH] svg-filters: create `gen_attr` and `gen_attrs` convenience macros --- crates/svg-filters/src/main.rs | 11 ++++- crates/svg-filters/src/types/nodes.rs | 2 +- .../svg-filters/src/types/nodes/primitives.rs | 17 ++++++++ .../src/types/nodes/primitives/blend.rs | 5 +-- .../types/nodes/primitives/color_matrix.rs | 36 +++++++---------- .../nodes/primitives/component_transfer.rs | 12 ++++++ .../src/types/nodes/primitives/composite.rs | 40 +++++++++++-------- .../src/types/nodes/primitives/flood.rs | 12 ++---- .../types/nodes/primitives/gaussian_blur.rs | 7 +--- .../src/types/nodes/primitives/morphology.rs | 12 ++---- .../src/types/nodes/primitives/offset.rs | 11 +---- .../src/types/nodes/primitives/turbulence.rs | 37 ++++------------- 12 files changed, 94 insertions(+), 108 deletions(-) diff --git a/crates/svg-filters/src/main.rs b/crates/svg-filters/src/main.rs index aff0c94..1bf86c8 100644 --- a/crates/svg-filters/src/main.rs +++ b/crates/svg-filters/src/main.rs @@ -4,7 +4,10 @@ use svg_filters::{ codegen::SvgDocument, types::{ graph::edge::Edge, - nodes::{primitives::color_matrix::ColorMatrixType, standard_input::StandardInput}, + nodes::{ + primitives::{blend::BlendMode, color_matrix::ColorMatrixType}, + standard_input::StandardInput, + }, }, Node, }; @@ -12,6 +15,12 @@ use svg_filters::{ fn main() { let mut doc = SvgDocument::new(); + let blend = doc.create_filter("blend"); + + let offset0 = blend.offset(StandardInput::SourceGraphic, 100., 0.); + let offset1 = blend.offset(StandardInput::SourceGraphic, -100., 0.); + blend.blend(offset0, offset1, BlendMode::Multiply); + eprintln!("{}", doc.generate_svg_pretty()); println!("{}", doc.generate_svg()); } diff --git a/crates/svg-filters/src/types/nodes.rs b/crates/svg-filters/src/types/nodes.rs index a1ca752..656574d 100644 --- a/crates/svg-filters/src/types/nodes.rs +++ b/crates/svg-filters/src/types/nodes.rs @@ -36,7 +36,7 @@ impl Default for Node { } #[derive(Default, Debug, Clone, Copy)] -pub(crate) struct CommonAttrs { +pub struct CommonAttrs { pub x: Coordinate, pub y: Coordinate, pub width: Length, diff --git a/crates/svg-filters/src/types/nodes/primitives.rs b/crates/svg-filters/src/types/nodes/primitives.rs index 7ba1c2d..a596639 100644 --- a/crates/svg-filters/src/types/nodes/primitives.rs +++ b/crates/svg-filters/src/types/nodes/primitives.rs @@ -4,6 +4,23 @@ use quick_xml::{events::attributes::Attribute, ElementWriter, Writer}; use super::CommonAttrs; +macro_rules! gen_attr { + ($name:literal = $out:expr) => { + quick_xml::events::attributes::Attribute { + key: quick_xml::name::QName($name), + value: std::borrow::Cow::from(($out).to_string().into_bytes()), + } + }; +} + +macro_rules! gen_attrs { + ($($name:literal = $out:expr),+) => { + vec![ + $(gen_attr!($name = $out)),+ + ] + }; +} + pub mod blend; pub mod color_matrix; pub mod component_transfer; diff --git a/crates/svg-filters/src/types/nodes/primitives/blend.rs b/crates/svg-filters/src/types/nodes/primitives/blend.rs index 8df8ad6..1887042 100644 --- a/crates/svg-filters/src/types/nodes/primitives/blend.rs +++ b/crates/svg-filters/src/types/nodes/primitives/blend.rs @@ -29,10 +29,7 @@ impl WriteElement for Blend { if let BlendMode::Normal = self.mode { Vec::new() } else { - vec![Attribute { - key: QName(b"mode"), - value: Cow::from(self.mode.to_string().into_bytes()), - }] + gen_attrs![b"mode" = self.mode] } } 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 4469500..31e4130 100644 --- a/crates/svg-filters/src/types/nodes/primitives/color_matrix.rs +++ b/crates/svg-filters/src/types/nodes/primitives/color_matrix.rs @@ -1,7 +1,3 @@ -use std::borrow::Cow; - -use quick_xml::{events::attributes::Attribute, name::QName}; - use super::WriteElement; /// [feColorMatrix](https://www.w3.org/TR/SVG11/filters.html#feColorMatrixElement) @@ -19,24 +15,20 @@ impl ColorMatrix { impl WriteElement for ColorMatrix { fn attrs(&self) -> Vec { match &self.cm_type { - ColorMatrixType::Matrix(v) => vec![Attribute { - key: QName(b"values"), - value: Cow::from( - v.iter() - .map(std::string::ToString::to_string) - .reduce(|mut acc, e| { - acc.push(' '); - acc.push_str(&e); - acc - }) - .expect("Should be able to concatenate the thingies") - .into_bytes(), - ), - }], - ColorMatrixType::Saturate(v) | ColorMatrixType::HueRotate(v) => vec![Attribute { - key: QName(b"values"), - value: Cow::from(v.to_string().into_bytes()), - }], + ColorMatrixType::Matrix(v) => gen_attrs![ + b"values" = v + .iter() + .map(std::string::ToString::to_string) + .reduce(|mut acc, e| { + acc.push(' '); + acc.push_str(&e); + acc + }) + .expect("fixed length arr should always work") + ], + ColorMatrixType::Saturate(v) | ColorMatrixType::HueRotate(v) => { + gen_attrs![b"values" = v] + } ColorMatrixType::LuminanceToAlpha => Vec::new(), } } 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 abfd5a0..d495ecc 100644 --- a/crates/svg-filters/src/types/nodes/primitives/component_transfer.rs +++ b/crates/svg-filters/src/types/nodes/primitives/component_transfer.rs @@ -1,3 +1,5 @@ +use super::WriteElement; + /// [feComponentTransfer](https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement) #[derive(Debug)] pub struct ComponentTransfer { @@ -7,6 +9,16 @@ pub struct ComponentTransfer { pub func_a: TransferFn, } +impl WriteElement for ComponentTransfer { + fn attrs(&self) -> Vec { + Vec::new() + } + + fn tag_name(&self) -> &'static str { + "feComponentTransfer" + } +} + /// [transfer functions](https://www.w3.org/TR/SVG11/filters.html#transferFuncElements) #[derive(Debug)] pub enum TransferFn { diff --git a/crates/svg-filters/src/types/nodes/primitives/composite.rs b/crates/svg-filters/src/types/nodes/primitives/composite.rs index e27664d..b877fe8 100644 --- a/crates/svg-filters/src/types/nodes/primitives/composite.rs +++ b/crates/svg-filters/src/types/nodes/primitives/composite.rs @@ -51,23 +51,29 @@ impl WriteElement for Composite { }]; if let Some([k1, k2, k3, k4]) = vals { - r.append(&mut vec![ - Attribute { - key: QName(b"k1"), - value: Cow::from(k1.to_string().into_bytes()), - }, - Attribute { - key: QName(b"k2"), - value: Cow::from(k2.to_string().into_bytes()), - }, - Attribute { - key: QName(b"k3"), - value: Cow::from(k3.to_string().into_bytes()), - }, - Attribute { - key: QName(b"k4"), - value: Cow::from(k4.to_string().into_bytes()), - }, + // r.append(&mut vec![ + // Attribute { + // key: QName(b"k1"), + // value: Cow::from(k1.to_string().into_bytes()), + // }, + // Attribute { + // key: QName(b"k2"), + // value: Cow::from(k2.to_string().into_bytes()), + // }, + // Attribute { + // key: QName(b"k3"), + // value: Cow::from(k3.to_string().into_bytes()), + // }, + // Attribute { + // key: QName(b"k4"), + // value: Cow::from(k4.to_string().into_bytes()), + // }, + // ]); + r.append(&mut gen_attrs![ + b"k1" = k1, + b"k2" = k2, + b"k3" = k3, + b"k4" = k4 ]); } diff --git a/crates/svg-filters/src/types/nodes/primitives/flood.rs b/crates/svg-filters/src/types/nodes/primitives/flood.rs index 3a90590..3342ef7 100644 --- a/crates/svg-filters/src/types/nodes/primitives/flood.rs +++ b/crates/svg-filters/src/types/nodes/primitives/flood.rs @@ -14,15 +14,9 @@ pub struct Flood { impl WriteElement for Flood { fn attrs(&self) -> Vec { - vec![ - Attribute { - key: QName(b"flood-color"), - value: Cow::from(self.flood_color.to_hex_string().into_bytes()), - }, - Attribute { - key: QName(b"flood-opacity"), - value: Cow::from(self.flood_opacity.to_string().into_bytes()), - }, + gen_attrs![ + b"flood-color" = self.flood_color.to_hex_string(), + b"flood-opacity" = self.flood_opacity ] } 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 a0c42bd..e255df4 100644 --- a/crates/svg-filters/src/types/nodes/primitives/gaussian_blur.rs +++ b/crates/svg-filters/src/types/nodes/primitives/gaussian_blur.rs @@ -26,12 +26,7 @@ impl GaussianBlur { impl WriteElement for GaussianBlur { fn attrs(&self) -> Vec { - vec![Attribute { - key: QName(b"stdDeviation"), - value: Cow::from( - format!("{} {}", self.std_deviation.0, self.std_deviation.1).into_bytes(), - ), - }] + gen_attrs![b"stdDeviation" = format!("{} {}", self.std_deviation.0, self.std_deviation.1)] } fn tag_name(&self) -> &'static str { diff --git a/crates/svg-filters/src/types/nodes/primitives/morphology.rs b/crates/svg-filters/src/types/nodes/primitives/morphology.rs index dc11775..f9087d6 100644 --- a/crates/svg-filters/src/types/nodes/primitives/morphology.rs +++ b/crates/svg-filters/src/types/nodes/primitives/morphology.rs @@ -13,15 +13,9 @@ pub struct Morphology { impl WriteElement for Morphology { fn attrs(&self) -> Vec { - vec![ - Attribute { - key: QName(b"operator"), - value: Cow::from(self.operator.to_string().into_bytes()), - }, - Attribute { - key: QName(b"radius"), - value: Cow::from(format!("{} {}", self.radius.0, self.radius.1).into_bytes()), - }, + gen_attrs![ + b"operator" = self.operator, + b"radius" = format!("{} {}", self.radius.0, self.radius.1) ] } diff --git a/crates/svg-filters/src/types/nodes/primitives/offset.rs b/crates/svg-filters/src/types/nodes/primitives/offset.rs index 4cad35b..fa17dca 100644 --- a/crates/svg-filters/src/types/nodes/primitives/offset.rs +++ b/crates/svg-filters/src/types/nodes/primitives/offset.rs @@ -19,16 +19,7 @@ impl Offset { impl WriteElement for Offset { fn attrs(&self) -> Vec { - vec![ - Attribute { - key: QName(b"dx"), - value: Cow::from(self.dx.to_string().into_bytes()), - }, - Attribute { - key: QName(b"dy"), - value: Cow::from(self.dy.to_string().into_bytes()), - }, - ] + gen_attrs![b"dx" = self.dx, b"dy" = self.dy] } fn tag_name(&self) -> &'static str { diff --git a/crates/svg-filters/src/types/nodes/primitives/turbulence.rs b/crates/svg-filters/src/types/nodes/primitives/turbulence.rs index 8bdcab0..d538006 100644 --- a/crates/svg-filters/src/types/nodes/primitives/turbulence.rs +++ b/crates/svg-filters/src/types/nodes/primitives/turbulence.rs @@ -1,10 +1,3 @@ -use std::borrow::Cow; - -use quick_xml::{ - events::attributes::{Attr, Attribute}, - name::QName, -}; - use super::WriteElement; /// [feTurbulence](https://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement) @@ -19,40 +12,26 @@ pub struct Turbulence { } impl WriteElement for Turbulence { + #[allow(clippy::str_to_string, reason = "in macro invocation")] fn attrs(&self) -> Vec { - let mut r = Vec::from([Attribute { - key: QName(b"baseFrequency"), - value: Cow::from( - format!("{} {}", self.base_frequency.0, self.base_frequency.1).into_bytes(), - ), - }]); + let mut r = gen_attrs!( + b"baseFrequency" = format!("{} {}", self.base_frequency.0, self.base_frequency.1) + ); if self.num_octaves != 1 { - r.push(Attribute { - key: QName(b"numOctaves"), - value: Cow::from(format!("{}", self.num_octaves).into_bytes()), - }); + r.push(gen_attr!(b"numOctaves" = self.num_octaves)); } if self.seed != 0 { - r.push(Attribute { - key: QName(b"seed"), - value: Cow::from(self.seed.to_string().into_bytes()), - }); + r.push(gen_attr!(b"seed" = self.seed)); } if self.stitch_tiles != StitchTiles::NoStitch { - r.push(Attribute { - key: QName(b"stitchTiles"), - value: Cow::from(b"stitch".to_vec()), - }); + r.push(gen_attr!(b"stitchTiles" = "stitch")); } if self.noise_type != NoiseType::Turbulence { - r.push(Attribute { - key: QName(b"type"), - value: Cow::from(b"fractalNoise".to_vec()), - }); + r.push(gen_attr!(b"type" = "fractalNoise")); } r