svg-filters & basic parser #15
12 changed files with 94 additions and 108 deletions
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<quick_xml::events::attributes::Attribute> {
|
||||
match &self.cm_type {
|
||||
ColorMatrixType::Matrix(v) => vec![Attribute {
|
||||
key: QName(b"values"),
|
||||
value: Cow::from(
|
||||
v.iter()
|
||||
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("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()),
|
||||
}],
|
||||
.expect("fixed length arr should always work")
|
||||
],
|
||||
ColorMatrixType::Saturate(v) | ColorMatrixType::HueRotate(v) => {
|
||||
gen_attrs![b"values" = v]
|
||||
}
|
||||
ColorMatrixType::LuminanceToAlpha => Vec::new(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<quick_xml::events::attributes::Attribute> {
|
||||
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 {
|
||||
|
|
|
@ -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
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,15 +14,9 @@ pub struct Flood {
|
|||
|
||||
impl WriteElement for Flood {
|
||||
fn attrs(&self) -> Vec<quick_xml::events::attributes::Attribute> {
|
||||
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
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -26,12 +26,7 @@ impl GaussianBlur {
|
|||
|
||||
impl WriteElement for GaussianBlur {
|
||||
fn attrs(&self) -> Vec<quick_xml::events::attributes::Attribute> {
|
||||
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 {
|
||||
|
|
|
@ -13,15 +13,9 @@ pub struct Morphology {
|
|||
|
||||
impl WriteElement for Morphology {
|
||||
fn attrs(&self) -> Vec<quick_xml::events::attributes::Attribute> {
|
||||
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)
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -19,16 +19,7 @@ impl Offset {
|
|||
|
||||
impl WriteElement for Offset {
|
||||
fn attrs(&self) -> Vec<quick_xml::events::attributes::Attribute> {
|
||||
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 {
|
||||
|
|
|
@ -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<quick_xml::events::attributes::Attribute> {
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue