diff options
author | Federico Mena Quintero <federico@gnome.org> | 2023-02-23 17:35:51 -0600 |
---|---|---|
committer | Federico Mena Quintero <federico@gnome.org> | 2023-02-23 17:41:12 -0600 |
commit | de8614dd81bea9aeab40daf2d24572174ae4873a (patch) | |
tree | 37ea7dfae32697eb8da5b06101d7d8a625e92827 | |
parent | 288119774d2a0a50c444fea8909c1661017ae703 (diff) | |
download | librsvg-de8614dd81bea9aeab40daf2d24572174ae4873a.tar.gz |
Simplify FeFunc* by using newtypes over a FeFuncCommon type
All of FeFunc{R,G,B,A} are the same except for the type name. So,
instead of duplicating all their code with a macro, extract the common
bits to a FeFuncCommon struct.
Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/801>
-rw-r--r-- | src/filter_func.rs | 68 | ||||
-rw-r--r-- | src/filters/component_transfer.rs | 252 |
2 files changed, 164 insertions, 156 deletions
diff --git a/src/filter_func.rs b/src/filter_func.rs index a3f8cbf6..a6611bf8 100644 --- a/src/filter_func.rs +++ b/src/filter_func.rs @@ -18,7 +18,7 @@ use crate::error::*; use crate::filter::Filter; use crate::filters::{ color_matrix::ColorMatrix, - component_transfer, + component_transfer::{self, FeFuncA, FeFuncB, FeFuncCommon, FeFuncG, FeFuncR}, composite::{Composite, Operator}, flood::Flood, gaussian_blur::GaussianBlur, @@ -293,22 +293,22 @@ impl Brightness { primitive: Primitive::default(), params: PrimitiveParams::ComponentTransfer(component_transfer::ComponentTransfer { functions: component_transfer::Functions { - r: component_transfer::FeFuncR { + r: FeFuncR(FeFuncCommon { function_type: component_transfer::FunctionType::Linear, slope, - ..component_transfer::FeFuncR::default() - }, - g: component_transfer::FeFuncG { + ..FeFuncCommon::default() + }), + g: FeFuncG(FeFuncCommon { function_type: component_transfer::FunctionType::Linear, slope, - ..component_transfer::FeFuncG::default() - }, - b: component_transfer::FeFuncB { + ..FeFuncCommon::default() + }), + b: FeFuncB(FeFuncCommon { function_type: component_transfer::FunctionType::Linear, slope, - ..component_transfer::FeFuncB::default() - }, - ..component_transfer::Functions::default() + ..FeFuncCommon::default() + }), + a: FeFuncA::default(), }, ..component_transfer::ComponentTransfer::default() }), @@ -332,25 +332,25 @@ impl Contrast { primitive: Primitive::default(), params: PrimitiveParams::ComponentTransfer(component_transfer::ComponentTransfer { functions: component_transfer::Functions { - r: component_transfer::FeFuncR { + r: FeFuncR(FeFuncCommon { function_type: component_transfer::FunctionType::Linear, slope, intercept, - ..component_transfer::FeFuncR::default() - }, - g: component_transfer::FeFuncG { + ..FeFuncCommon::default() + }), + g: FeFuncG(FeFuncCommon { function_type: component_transfer::FunctionType::Linear, slope, intercept, - ..component_transfer::FeFuncG::default() - }, - b: component_transfer::FeFuncB { + ..FeFuncCommon::default() + }), + b: FeFuncB(FeFuncCommon { function_type: component_transfer::FunctionType::Linear, slope, intercept, - ..component_transfer::FeFuncB::default() - }, - ..component_transfer::Functions::default() + ..FeFuncCommon::default() + }), + a: FeFuncA::default(), }, ..component_transfer::ComponentTransfer::default() }), @@ -501,22 +501,22 @@ impl Invert { primitive: Primitive::default(), params: PrimitiveParams::ComponentTransfer(component_transfer::ComponentTransfer { functions: component_transfer::Functions { - r: component_transfer::FeFuncR { + r: FeFuncR(FeFuncCommon { function_type: component_transfer::FunctionType::Table, table_values: vec![p, 1.0 - p], - ..component_transfer::FeFuncR::default() - }, - g: component_transfer::FeFuncG { + ..FeFuncCommon::default() + }), + g: FeFuncG(FeFuncCommon { function_type: component_transfer::FunctionType::Table, table_values: vec![p, 1.0 - p], - ..component_transfer::FeFuncG::default() - }, - b: component_transfer::FeFuncB { + ..FeFuncCommon::default() + }), + b: FeFuncB(FeFuncCommon { function_type: component_transfer::FunctionType::Table, table_values: vec![p, 1.0 - p], - ..component_transfer::FeFuncB::default() - }, - ..component_transfer::Functions::default() + ..FeFuncCommon::default() + }), + a: FeFuncA::default(), }, ..component_transfer::ComponentTransfer::default() }), @@ -539,11 +539,11 @@ impl Opacity { primitive: Primitive::default(), params: PrimitiveParams::ComponentTransfer(component_transfer::ComponentTransfer { functions: component_transfer::Functions { - a: component_transfer::FeFuncA { + a: FeFuncA(FeFuncCommon { function_type: component_transfer::FunctionType::Table, table_values: vec![0.0, p], - ..component_transfer::FeFuncA::default() - }, + ..FeFuncCommon::default() + }), ..component_transfer::Functions::default() }, ..component_transfer::ComponentTransfer::default() diff --git a/src/filters/component_transfer.rs b/src/filters/component_transfer.rs index e233980d..cd54db2c 100644 --- a/src/filters/component_transfer.rs +++ b/src/filters/component_transfer.rs @@ -132,129 +132,141 @@ fn gamma(params: &FunctionParameters, value: f64) -> f64 { params.amplitude * value.powf(params.exponent) + params.offset } -trait FeComponentTransferFunc { - /// Returns the component transfer function. - fn function(&self) -> Function; - - /// Returns the component transfer function parameters. - fn function_parameters(&self) -> FunctionParameters; +/// Common values for `feFuncX` elements +/// +/// The elements `feFuncR`, `feFuncG`, `feFuncB`, `feFuncA` all have the same parameters; this structure +/// contains them. Later we define newtypes on this struct as [`FeFuncR`], etc. +#[derive(Clone, Debug, PartialEq)] +pub struct FeFuncCommon { + pub function_type: FunctionType, + pub table_values: Vec<f64>, + pub slope: f64, + pub intercept: f64, + pub amplitude: f64, + pub exponent: f64, + pub offset: f64, } -macro_rules! func_x { - ($func_name:ident) => { - #[derive(Clone, Debug, PartialEq)] - pub struct $func_name { - pub function_type: FunctionType, - pub table_values: Vec<f64>, - pub slope: f64, - pub intercept: f64, - pub amplitude: f64, - pub exponent: f64, - pub offset: f64, +impl Default for FeFuncCommon { + #[inline] + fn default() -> Self { + Self { + function_type: FunctionType::Identity, + table_values: Vec::new(), + slope: 1.0, + intercept: 0.0, + amplitude: 1.0, + exponent: 1.0, + offset: 0.0, } + } +} - impl Default for $func_name { - #[inline] - fn default() -> Self { - Self { - function_type: FunctionType::Identity, - table_values: Vec::new(), - slope: 1.0, - intercept: 0.0, - amplitude: 1.0, - exponent: 1.0, - offset: 0.0, - } +// All FeFunc* elements are defined here; they just delegate their attributes +// to the FeFuncCommon inside. +macro_rules! impl_func { + ($(#[$attr:meta])* + $name:ident + ) => { + #[derive(Clone, Debug, Default, PartialEq)] + pub struct $name(pub FeFuncCommon); + + impl SetAttributes for $name { + fn set_attributes(&mut self, attrs: &Attributes, session: &Session) { + self.0.set_attributes(attrs, session); } } - impl FeComponentTransferFunc for $func_name { - #[inline] - fn function_parameters(&self) -> FunctionParameters { - FunctionParameters { - table_values: self.table_values.clone(), - slope: self.slope, - intercept: self.intercept, - amplitude: self.amplitude, - exponent: self.exponent, - offset: self.offset, - } - } + impl Draw for $name {} + }; +} + +impl_func!( + /// The `feFuncR` element. + FeFuncR +); + +impl_func!( + /// The `feFuncG` element. + FeFuncG +); + +impl_func!( + /// The `feFuncB` element. + FeFuncB +); - #[inline] - fn function(&self) -> Function { - match self.function_type { - FunctionType::Identity => identity, - FunctionType::Table => table, - FunctionType::Discrete => discrete, - FunctionType::Linear => linear, - FunctionType::Gamma => gamma, +impl_func!( + /// The `feFuncA` element. + FeFuncA +); + +impl FeFuncCommon { + fn set_attributes(&mut self, attrs: &Attributes, session: &Session) { + for (attr, value) in attrs.iter() { + match attr.expanded() { + expanded_name!("", "type") => { + set_attribute(&mut self.function_type, attr.parse(value), session) + } + expanded_name!("", "tableValues") => { + // #691: Limit list to 256 to mitigate malicious SVGs + let mut number_list = NumberList::<0, 256>(Vec::new()); + set_attribute(&mut number_list, attr.parse(value), session); + self.table_values = number_list.0; + } + expanded_name!("", "slope") => { + set_attribute(&mut self.slope, attr.parse(value), session) } + expanded_name!("", "intercept") => { + set_attribute(&mut self.intercept, attr.parse(value), session) + } + expanded_name!("", "amplitude") => { + set_attribute(&mut self.amplitude, attr.parse(value), session) + } + expanded_name!("", "exponent") => { + set_attribute(&mut self.exponent, attr.parse(value), session) + } + expanded_name!("", "offset") => { + set_attribute(&mut self.offset, attr.parse(value), session) + } + + _ => (), } } - impl SetAttributes for $func_name { - #[inline] - fn set_attributes(&mut self, attrs: &Attributes, session: &Session) { - for (attr, value) in attrs.iter() { - match attr.expanded() { - expanded_name!("", "type") => { - set_attribute(&mut self.function_type, attr.parse(value), session) - } - expanded_name!("", "tableValues") => { - // #691: Limit list to 256 to mitigate malicious SVGs - let mut number_list = NumberList::<0, 256>(Vec::new()); - set_attribute(&mut number_list, attr.parse(value), session); - self.table_values = number_list.0; - } - expanded_name!("", "slope") => { - set_attribute(&mut self.slope, attr.parse(value), session) - } - expanded_name!("", "intercept") => { - set_attribute(&mut self.intercept, attr.parse(value), session) - } - expanded_name!("", "amplitude") => { - set_attribute(&mut self.amplitude, attr.parse(value), session) - } - expanded_name!("", "exponent") => { - set_attribute(&mut self.exponent, attr.parse(value), session) - } - expanded_name!("", "offset") => { - set_attribute(&mut self.offset, attr.parse(value), session) - } - - _ => (), - } - } - - // The table function type with empty table_values is considered - // an identity function. - match self.function_type { - FunctionType::Table | FunctionType::Discrete => { - if self.table_values.is_empty() { - self.function_type = FunctionType::Identity; - } - } - _ => (), + // The table function type with empty table_values is considered + // an identity function. + match self.function_type { + FunctionType::Table | FunctionType::Discrete => { + if self.table_values.is_empty() { + self.function_type = FunctionType::Identity; } } + _ => (), } + } - impl Draw for $func_name {} - }; -} - -// The `<feFuncR>` element -func_x!(FeFuncR); - -// The `<feFuncG>` element -func_x!(FeFuncG); - -// The `<feFuncB>` element -func_x!(FeFuncB); + fn function_parameters(&self) -> FunctionParameters { + FunctionParameters { + table_values: self.table_values.clone(), + slope: self.slope, + intercept: self.intercept, + amplitude: self.amplitude, + exponent: self.exponent, + offset: self.offset, + } + } -// The `<feFuncA>` element -func_x!(FeFuncA); + fn function(&self) -> Function { + match self.function_type { + FunctionType::Identity => identity, + FunctionType::Table => table, + FunctionType::Discrete => discrete, + FunctionType::Linear => linear, + FunctionType::Gamma => gamma, + } + } +} macro_rules! func_or_default { ($func_node:ident, $func_type:ident) => { @@ -305,11 +317,7 @@ impl ComponentTransfer { input_1.surface().surface_type(), )?; - #[inline] - fn compute_func<F>(func: &F) -> impl Fn(u8, f64, f64) -> u8 - where - F: FeComponentTransferFunc, - { + fn compute_func(func: &FeFuncCommon) -> impl Fn(u8, f64, f64) -> u8 { let compute = func.function(); let params = func.function_parameters(); @@ -325,13 +333,13 @@ impl ComponentTransfer { } } - let compute_r = compute_func::<FeFuncR>(&self.functions.r); - let compute_g = compute_func::<FeFuncG>(&self.functions.g); - let compute_b = compute_func::<FeFuncB>(&self.functions.b); + let compute_r = compute_func(&self.functions.r.0); + let compute_g = compute_func(&self.functions.g.0); + let compute_b = compute_func(&self.functions.b.0); // Alpha gets special handling since everything else depends on it. - let compute_a = self.functions.a.function(); - let params_a = self.functions.a.function_parameters(); + let compute_a = self.functions.a.0.function(); + let params_a = self.functions.a.0.function_parameters(); let compute_a = |alpha| compute_a(¶ms_a, alpha); // Do the actual processing. @@ -428,13 +436,13 @@ mod tests { Functions { r: FeFuncR::default(), - g: FeFuncG { + g: FeFuncG(FeFuncCommon { function_type: FunctionType::Table, table_values: vec![0.0, 1.0, 2.0], - ..FeFuncG::default() - }, + ..FeFuncCommon::default() + }), - b: FeFuncB { + b: FeFuncB(FeFuncCommon { function_type: FunctionType::Discrete, table_values: vec![0.0, 1.0], slope: 1.0, @@ -442,8 +450,8 @@ mod tests { amplitude: 3.0, exponent: 4.0, offset: 5.0, - ..FeFuncB::default() - }, + ..FeFuncCommon::default() + }), a: FeFuncA::default(), } |