134 lines
4.3 KiB
Rust
134 lines
4.3 KiB
Rust
use quick_xml::{events::attributes::Attribute, Writer};
|
|
|
|
use super::WriteElement;
|
|
|
|
/// [feComponentTransfer](https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement)
|
|
#[derive(Debug)]
|
|
pub struct ComponentTransfer {
|
|
pub func_r: TransferFn,
|
|
pub func_g: TransferFn,
|
|
pub func_b: TransferFn,
|
|
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"
|
|
}
|
|
|
|
fn element_writer<'writer, 'result>(
|
|
&self,
|
|
writer: &'writer mut quick_xml::Writer<&'result mut Vec<u8>>,
|
|
common: crate::types::nodes::CommonAttrs,
|
|
inputs: Vec<String>,
|
|
output: Option<String>,
|
|
) -> quick_xml::Result<&'writer mut quick_xml::Writer<&'result mut Vec<u8>>> {
|
|
let inputs: Vec<_> = inputs
|
|
.into_iter()
|
|
.enumerate()
|
|
.map(|(i, edge)| {
|
|
(
|
|
match i {
|
|
0 => "in".to_owned(),
|
|
n => format!("in{}", n + 1),
|
|
}
|
|
.into_bytes(),
|
|
edge.into_bytes(),
|
|
)
|
|
})
|
|
.collect();
|
|
let mut el_writer = writer
|
|
.create_element(self.tag_name())
|
|
.with_attributes(inputs.iter().map(|(k, v)| (&k[..], &v[..])))
|
|
.with_attributes(Into::<Vec<Attribute<'_>>>::into(common));
|
|
if let Some(output) = output {
|
|
el_writer = el_writer.with_attribute(("result", output.as_str()));
|
|
}
|
|
|
|
el_writer.write_inner_content(|writer| {
|
|
self.func_r.write_self(writer, "feFuncR")?;
|
|
self.func_g.write_self(writer, "feFuncG")?;
|
|
self.func_b.write_self(writer, "feFuncB")?;
|
|
self.func_a.write_self(writer, "feFuncA")?;
|
|
Ok(())
|
|
})
|
|
}
|
|
}
|
|
|
|
/// [transfer functions](https://www.w3.org/TR/SVG11/filters.html#transferFuncElements)
|
|
#[derive(Debug, Clone)]
|
|
pub enum TransferFn {
|
|
Identity,
|
|
Table {
|
|
table_values: Vec<f32>,
|
|
},
|
|
Discrete {
|
|
table_values: Vec<f32>,
|
|
},
|
|
Linear {
|
|
slope: f32,
|
|
intercept: f32,
|
|
},
|
|
Gamma {
|
|
amplitude: f32,
|
|
exponent: f32,
|
|
offset: f32,
|
|
},
|
|
}
|
|
|
|
impl TransferFn {
|
|
#[allow(clippy::str_to_string, reason = "inside macro call")]
|
|
fn write_self<'writer, 'result>(
|
|
&self,
|
|
target: &'writer mut Writer<&'result mut Vec<u8>>,
|
|
name: &'static str,
|
|
) -> quick_xml::Result<&'writer mut Writer<&'result mut Vec<u8>>> {
|
|
target
|
|
.create_element(name)
|
|
.with_attributes(match self {
|
|
TransferFn::Identity => gen_attrs![b"type": "identity"],
|
|
TransferFn::Table { table_values } => gen_attrs![
|
|
b"type": "table",
|
|
b"tableValues": table_values
|
|
.iter()
|
|
.map(std::string::ToString::to_string)
|
|
.reduce(|mut acc, e| {
|
|
acc.push(' ');
|
|
acc.push_str(&e);
|
|
acc
|
|
}).expect("empty tables disallowed")
|
|
],
|
|
TransferFn::Discrete { table_values } => gen_attrs![
|
|
b"type": "discrete",
|
|
b"tableValues": table_values
|
|
.iter()
|
|
.map(std::string::ToString::to_string)
|
|
.reduce(|mut acc, e| {
|
|
acc.push(' ');
|
|
acc.push_str(&e);
|
|
acc
|
|
}).expect("empty tables disallowed")
|
|
],
|
|
TransferFn::Linear { slope, intercept } => gen_attrs![
|
|
b"type": "linear",
|
|
b"slope": slope,
|
|
b"intercept": intercept
|
|
],
|
|
TransferFn::Gamma {
|
|
amplitude,
|
|
exponent,
|
|
offset,
|
|
} => gen_attrs![
|
|
b"type": "gamma",
|
|
b"amplitude": amplitude,
|
|
b"exponent": exponent,
|
|
b"offset": offset
|
|
],
|
|
})
|
|
.write_empty()
|
|
}
|
|
}
|