summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@gnome.org>2023-02-23 17:35:51 -0600
committerFederico Mena Quintero <federico@gnome.org>2023-02-23 17:41:12 -0600
commitde8614dd81bea9aeab40daf2d24572174ae4873a (patch)
tree37ea7dfae32697eb8da5b06101d7d8a625e92827
parent288119774d2a0a50c444fea8909c1661017ae703 (diff)
downloadlibrsvg-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.rs68
-rw-r--r--src/filters/component_transfer.rs252
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(&params_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(),
}