forked from katzen-cafe/iowo
Compare commits
No commits in common. "f59062cf88685f5e7847b8b09361d55ed41c25b3" and "bf60bdd81426536acb5fffac24d99f1c449e9a76" have entirely different histories.
f59062cf88
...
bf60bdd814
11 changed files with 58 additions and 153 deletions
|
@ -43,25 +43,10 @@ impl SvgDocument {
|
||||||
self.filters.get_mut(&id.to_string()).unwrap()
|
self.filters.get_mut(&id.to_string()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_svg_pretty(&self) -> String {
|
|
||||||
let mut result = Vec::new();
|
|
||||||
let doc_writer = quick_xml::Writer::new_with_indent(&mut result, b' ', 2);
|
|
||||||
|
|
||||||
self.generate(doc_writer);
|
|
||||||
|
|
||||||
String::from_utf8_lossy(&result).to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_svg(&self) -> String {
|
pub fn generate_svg(&self) -> String {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
let doc_writer = quick_xml::Writer::new(&mut result);
|
let mut doc_writer = quick_xml::Writer::new_with_indent(&mut result, b' ', 2);
|
||||||
|
|
||||||
self.generate(doc_writer);
|
|
||||||
|
|
||||||
String::from_utf8_lossy(&result).to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate(&self, mut doc_writer: quick_xml::Writer<&mut Vec<u8>>) {
|
|
||||||
doc_writer
|
doc_writer
|
||||||
.create_element("svg")
|
.create_element("svg")
|
||||||
.write_inner_content(|writer| {
|
.write_inner_content(|writer| {
|
||||||
|
@ -70,6 +55,8 @@ impl SvgDocument {
|
||||||
.try_fold(writer, Self::gen_filter)
|
.try_fold(writer, Self::gen_filter)
|
||||||
.map(|_| {})
|
.map(|_| {})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
String::from_utf8_lossy(&result).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_filter<'w, 'r>(
|
fn gen_filter<'w, 'r>(
|
||||||
|
|
|
@ -5,4 +5,4 @@ pub mod types;
|
||||||
pub use types::nodes::Node;
|
pub use types::nodes::Node;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests {}
|
||||||
|
|
|
@ -10,8 +10,51 @@ use svg_filters::{
|
||||||
};
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut doc = SvgDocument::new();
|
// <filter id="chromabb" >
|
||||||
|
// <feColorMatrix values="1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceGraphic" />
|
||||||
|
// <feOffset dx="25" dy="0" />
|
||||||
|
// <feGaussianBlur stdDeviation="5 0" result="red" />
|
||||||
|
|
||||||
|
// <feColorMatrix values="0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0" result="grn" in="SourceGraphic" />
|
||||||
|
|
||||||
|
// <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0" in="SourceGraphic" />
|
||||||
|
// <feOffset dx="-25" dy="0" />
|
||||||
|
// <feGaussianBlur stdDeviation="5 0" result="blu"/>
|
||||||
|
|
||||||
|
// <feComposite in="red" in2="blu" operator="arithmetic" k2="1" k3="1" result="rb" />
|
||||||
|
// <feComposite in="rb" in2="grn" operator="arithmetic" k2="1" k3="1" />
|
||||||
|
// </filter>
|
||||||
|
|
||||||
|
let mut doc = SvgDocument::new();
|
||||||
|
let chromabb = doc.create_filter("chromabb_gen");
|
||||||
|
|
||||||
|
let chan_r = chromabb.color_matrix(
|
||||||
|
StandardInput::SourceGraphic,
|
||||||
|
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 offset_r = chromabb.offset(chan_r, 25., 0.);
|
||||||
|
let blur_r = chromabb.gaussian_blur_xy(offset_r, 5, 0);
|
||||||
|
|
||||||
|
let chan_b = chromabb.color_matrix(
|
||||||
|
StandardInput::SourceGraphic,
|
||||||
|
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_b = chromabb.offset(chan_b, -25., 0.);
|
||||||
|
let blur_b = chromabb.gaussian_blur_xy(offset_b, 5, 0);
|
||||||
|
|
||||||
|
let composite_rb = chromabb.composite_arithmetic(blur_r, blur_b, 0., 1., 1., 0.);
|
||||||
|
|
||||||
|
let chan_g = chromabb.color_matrix(
|
||||||
|
StandardInput::SourceGraphic,
|
||||||
|
ColorMatrixType::Matrix(Box::new([
|
||||||
|
0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.,
|
||||||
|
])),
|
||||||
|
);
|
||||||
|
chromabb.composite_arithmetic(composite_rb, chan_g, 0., 1., 1., 0.);
|
||||||
|
|
||||||
eprintln!("{}", doc.generate_svg_pretty());
|
|
||||||
println!("{}", doc.generate_svg());
|
println!("{}", doc.generate_svg());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
mod color_matrix;
|
|
||||||
|
|
||||||
mod complex;
|
|
||||||
mod gaussian_blur;
|
|
||||||
mod offset;
|
|
||||||
|
|
||||||
mod blend {}
|
|
||||||
mod component_transfer {}
|
|
||||||
mod composite {}
|
|
||||||
mod convolve_matrix {}
|
|
||||||
mod diffuse_lighting {}
|
|
||||||
mod displacement_map {}
|
|
||||||
mod flood {}
|
|
||||||
mod image {}
|
|
||||||
mod merge {}
|
|
||||||
mod morphology {}
|
|
||||||
mod specular_lighting {}
|
|
||||||
mod tile {}
|
|
||||||
mod turbulence {}
|
|
|
@ -1,25 +0,0 @@
|
||||||
use crate::{
|
|
||||||
codegen::SvgDocument,
|
|
||||||
types::nodes::{primitives::color_matrix::ColorMatrixType, standard_input::StandardInput},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_greyscale_channel_extraction() {
|
|
||||||
let mut doc = SvgDocument::new();
|
|
||||||
let greyscale = doc.create_filter("greyscale");
|
|
||||||
|
|
||||||
greyscale.color_matrix(
|
|
||||||
StandardInput::SourceGraphic,
|
|
||||||
ColorMatrixType::Matrix(Box::new([
|
|
||||||
1., 0., 0., 0., 0., //
|
|
||||||
1., 0., 0., 0., 0., //
|
|
||||||
1., 0., 0., 0., 0., //
|
|
||||||
0., 0., 0., 1., 0.,
|
|
||||||
])),
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
doc.generate_svg(),
|
|
||||||
r#"<svg><filter id="greyscale"><feColorMatrix values="1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0" in="SourceGraphic"/></filter></svg>"#
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
use crate::{
|
|
||||||
codegen::SvgDocument,
|
|
||||||
types::nodes::{primitives::color_matrix::ColorMatrixType, standard_input::StandardInput},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_chrom_abb() {
|
|
||||||
let mut doc = SvgDocument::new();
|
|
||||||
let chromabb = doc.create_filter("chromabb_gen");
|
|
||||||
|
|
||||||
let chan_r = chromabb.color_matrix(
|
|
||||||
StandardInput::SourceGraphic,
|
|
||||||
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 offset_r = chromabb.offset(chan_r, 25., 0.);
|
|
||||||
let blur_r = chromabb.gaussian_blur_xy(offset_r, 5, 0);
|
|
||||||
|
|
||||||
let chan_b = chromabb.color_matrix(
|
|
||||||
StandardInput::SourceGraphic,
|
|
||||||
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_b = chromabb.offset(chan_b, -25., 0.);
|
|
||||||
let blur_b = chromabb.gaussian_blur_xy(offset_b, 5, 0);
|
|
||||||
|
|
||||||
let composite_rb = chromabb.composite_arithmetic(blur_r, blur_b, 0., 1., 1., 0.);
|
|
||||||
|
|
||||||
let chan_g = chromabb.color_matrix(
|
|
||||||
StandardInput::SourceGraphic,
|
|
||||||
ColorMatrixType::Matrix(Box::new([
|
|
||||||
0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.,
|
|
||||||
])),
|
|
||||||
);
|
|
||||||
chromabb.composite_arithmetic(composite_rb, chan_g, 0., 1., 1., 0.);
|
|
||||||
assert_eq!(
|
|
||||||
doc.generate_svg(),
|
|
||||||
r#"<svg><filter id="chromabb_gen"><feColorMatrix values="0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceGraphic" result="r13"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0" in="SourceGraphic" result="r9"/><feOffset dx="-25" dy="0" in="r9" result="r10"/><feGaussianBlur stdDeviation="5 0" in="r10" result="r11"/><feColorMatrix values="1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceGraphic" result="r6"/><feOffset dx="25" dy="0" in="r6" result="r7"/><feGaussianBlur stdDeviation="5 0" in="r7" result="r8"/><feComposite operator="arithmetic" k1="0" k2="1" k3="1" k4="0" in="r8" in2="r11" result="r12"/><feComposite operator="arithmetic" k1="0" k2="1" k3="1" k4="0" in="r12" in2="r13"/></filter></svg>"#
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
use crate::{codegen::SvgDocument, types::nodes::standard_input::StandardInput};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_simple_blur() {
|
|
||||||
let mut doc = SvgDocument::new();
|
|
||||||
let blur = doc.create_filter("blur");
|
|
||||||
|
|
||||||
blur.gaussian_blur_xy(StandardInput::SourceGraphic, 30, 30);
|
|
||||||
assert_eq!(
|
|
||||||
doc.generate_svg(),
|
|
||||||
r#"<svg><filter id="blur"><feGaussianBlur stdDeviation="30 30" in="SourceGraphic"/></filter></svg>"#
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
use crate::{codegen::SvgDocument, types::nodes::standard_input::StandardInput};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_offset_simple() {
|
|
||||||
let mut doc = SvgDocument::new();
|
|
||||||
let mut offset = doc.create_filter("offset");
|
|
||||||
|
|
||||||
offset.offset(StandardInput::SourceGraphic, 25., -25.);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
doc.generate_svg(),
|
|
||||||
r#"<svg><filter id="offset"><feOffset dx="25" dy="-25" in="SourceGraphic"/></filter></svg>"#
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -6,7 +6,6 @@ use self::{
|
||||||
primitives::{
|
primitives::{
|
||||||
blend::{Blend, BlendMode},
|
blend::{Blend, BlendMode},
|
||||||
color_matrix::{ColorMatrix, ColorMatrixType},
|
color_matrix::{ColorMatrix, ColorMatrixType},
|
||||||
component_transfer::{ComponentTransfer, TransferFn},
|
|
||||||
composite::{Composite, CompositeOperator},
|
composite::{Composite, CompositeOperator},
|
||||||
gaussian_blur::GaussianBlur,
|
gaussian_blur::GaussianBlur,
|
||||||
offset::Offset,
|
offset::Offset,
|
||||||
|
@ -146,7 +145,9 @@ impl Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn composite_arithmetic(k1: f32, k2: f32, k3: f32, k4: f32) -> Self {
|
pub fn composite_arithmetic(k1: f32, k2: f32, k3: f32, k4: f32) -> Self {
|
||||||
Self::composite(CompositeOperator::Arithmetic { k1, k2, k3, k4 })
|
Self::simple(FePrimitive::Composite(Composite::arithmetic(
|
||||||
|
k1, k2, k3, k4,
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gaussian_blur(v: u16) -> Self {
|
pub fn gaussian_blur(v: u16) -> Self {
|
||||||
|
@ -160,18 +161,4 @@ impl Node {
|
||||||
pub fn offset(dx: f32, dy: f32) -> Self {
|
pub fn offset(dx: f32, dy: f32) -> Self {
|
||||||
Self::simple(FePrimitive::Offset(Offset::new(dx, dy)))
|
Self::simple(FePrimitive::Offset(Offset::new(dx, dy)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn component_transfer_rgba(
|
|
||||||
r: TransferFn,
|
|
||||||
g: TransferFn,
|
|
||||||
b: TransferFn,
|
|
||||||
a: TransferFn,
|
|
||||||
) -> Self {
|
|
||||||
Self::simple(FePrimitive::ComponentTransfer(ComponentTransfer {
|
|
||||||
func_r: r,
|
|
||||||
func_g: g,
|
|
||||||
func_b: b,
|
|
||||||
func_a: a,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ pub trait WriteElement {
|
||||||
/// svg filter effects primitives
|
/// svg filter effects primitives
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum FePrimitive {
|
pub enum FePrimitive {
|
||||||
|
// 2 inputs
|
||||||
Blend(blend::Blend),
|
Blend(blend::Blend),
|
||||||
ColorMatrix(color_matrix::ColorMatrix),
|
ColorMatrix(color_matrix::ColorMatrix),
|
||||||
ComponentTransfer(component_transfer::ComponentTransfer),
|
ComponentTransfer(component_transfer::ComponentTransfer),
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
/// [feComponentTransfer](https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement)
|
/// [feComponentTransfer](https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ComponentTransfer {
|
pub struct ComponentTransfer {
|
||||||
pub func_r: TransferFn,
|
func_r: TransferFunction,
|
||||||
pub func_g: TransferFn,
|
func_g: TransferFunction,
|
||||||
pub func_b: TransferFn,
|
func_b: TransferFunction,
|
||||||
pub func_a: TransferFn,
|
func_a: TransferFunction,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [transfer functions](https://www.w3.org/TR/SVG11/filters.html#transferFuncElements)
|
/// [transfer functions](https://www.w3.org/TR/SVG11/filters.html#transferFuncElements)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum TransferFn {
|
enum TransferFunction {
|
||||||
Identity,
|
Identity,
|
||||||
Table {
|
Table {
|
||||||
table_values: Vec<f32>,
|
table_values: Vec<f32>,
|
||||||
|
|
Loading…
Reference in a new issue