[librsvg: 1/5] component_transfer: split FuncA, FuncR, FuncG, FuncB nodes.
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 1/5] component_transfer: split FuncA, FuncR, FuncG, FuncB nodes.
- Date: Wed, 16 Oct 2019 15:40:14 +0000 (UTC)
commit c17b9c8315dc91ab12f8360c75131d01552c89ee
Author: Paolo Borelli <pborelli gnome org>
Date: Tue Oct 15 08:58:06 2019 +0200
component_transfer: split FuncA, FuncR, FuncG, FuncB nodes.
Use a macro to generate the four variants. Each one implements
the ComponentTransferFunc trait.
rsvg_internals/src/create_node.rs | 10 +-
rsvg_internals/src/filters/component_transfer.rs | 362 ++++++++++++-----------
2 files changed, 190 insertions(+), 182 deletions(-)
---
diff --git a/rsvg_internals/src/create_node.rs b/rsvg_internals/src/create_node.rs
index a63279c0..f1650cd6 100644
--- a/rsvg_internals/src/create_node.rs
+++ b/rsvg_internals/src/create_node.rs
@@ -6,7 +6,7 @@ use crate::clip_path::NodeClipPath;
use crate::filters::{
blend::Blend,
color_matrix::ColorMatrix,
- component_transfer::{ComponentTransfer, FuncX},
+ component_transfer::{ComponentTransfer, FuncA, FuncB, FuncG, FuncR},
composite::Composite,
convolve_matrix::ConvolveMatrix,
displacement_map::DisplacementMap,
@@ -61,10 +61,10 @@ mod creators {
n!(create_blend, FeBlend, Blend::default);
n!(create_color_matrix, FeColorMatrix, ColorMatrix::default);
n!(create_component_transfer, FeComponentTransfer, ComponentTransfer::default);
- n!(create_component_transfer_func_a, ComponentTransferFunctionA, FuncX::new_a);
- n!(create_component_transfer_func_b, ComponentTransferFunctionB, FuncX::new_b);
- n!(create_component_transfer_func_g, ComponentTransferFunctionG, FuncX::new_g);
- n!(create_component_transfer_func_r, ComponentTransferFunctionR, FuncX::new_r);
+ n!(create_component_transfer_func_a, ComponentTransferFunctionA, FuncA::default);
+ n!(create_component_transfer_func_b, ComponentTransferFunctionB, FuncB::default);
+ n!(create_component_transfer_func_g, ComponentTransferFunctionG, FuncG::default);
+ n!(create_component_transfer_func_r, ComponentTransferFunctionR, FuncR::default);
n!(create_composite, FeComposite, Composite::default);
n!(create_convolve_matrix, FeConvolveMatrix, ConvolveMatrix::default);
n!(create_defs, Defs, NodeNonRendering::default);
diff --git a/rsvg_internals/src/filters/component_transfer.rs
b/rsvg_internals/src/filters/component_transfer.rs
index a18f01da..7bd37669 100644
--- a/rsvg_internals/src/filters/component_transfer.rs
+++ b/rsvg_internals/src/filters/component_transfer.rs
@@ -25,6 +25,25 @@ pub struct ComponentTransfer {
base: PrimitiveWithInput,
}
+impl Default for ComponentTransfer {
+ /// Constructs a new `ComponentTransfer` with empty properties.
+ #[inline]
+ fn default() -> ComponentTransfer {
+ ComponentTransfer {
+ base: PrimitiveWithInput::new::<Self>(),
+ }
+ }
+}
+
+impl NodeTrait for ComponentTransfer {
+ impl_node_as_filter!();
+
+ #[inline]
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ self.base.set_atts(parent, pbag)
+ }
+}
+
/// Pixel components that can be influenced by `feComponentTransfer`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Channel {
@@ -44,16 +63,20 @@ enum FunctionType {
Gamma,
}
-/// The `<feFuncX>` element (X is R, G, B or A).
-pub struct FuncX {
- channel: Channel,
- function_type: FunctionType,
- table_values: Vec<f64>,
- slope: f64,
- intercept: f64,
- amplitude: f64,
- exponent: f64,
- offset: f64,
+impl FunctionType {
+ fn parse(attr: LocalName, s: &str) -> Result<Self, NodeError> {
+ match s {
+ "identity" => Ok(FunctionType::Identity),
+ "table" => Ok(FunctionType::Table),
+ "discrete" => Ok(FunctionType::Discrete),
+ "linear" => Ok(FunctionType::Linear),
+ "gamma" => Ok(FunctionType::Gamma),
+ _ => Err(NodeError::parse_error(
+ attr,
+ ParseError::new("invalid value"),
+ )),
+ }
+ }
}
/// The compute function parameters.
@@ -111,157 +134,155 @@ fn gamma(params: &FunctionParameters<'_>, value: f64) -> f64 {
params.amplitude * value.powf(params.exponent) + params.offset
}
-impl Default for ComponentTransfer {
- /// Constructs a new `ComponentTransfer` with empty properties.
- #[inline]
- fn default() -> ComponentTransfer {
- ComponentTransfer {
- base: PrimitiveWithInput::new::<Self>(),
- }
- }
-}
+trait ComponentTransferFunc {
+ /// Returns the component transfer function.
+ fn function(&self) -> Function;
-impl Default for FuncX {
- #[inline]
- fn default() -> Self {
- Self {
- channel: Channel::R,
- function_type: FunctionType::Identity,
- table_values: Vec::new(),
- slope: 1.0,
- intercept: 0.0,
- amplitude: 1.0,
- exponent: 1.0,
- offset: 0.0,
- }
- }
-}
+ /// Returns the component transfer function parameters.
+ fn function_parameters(&self) -> FunctionParameters<'_>;
-impl FuncX {
- /// Constructs a new `FuncR` with empty properties.
- #[inline]
- pub fn new_r() -> Self {
- Self {
- channel: Channel::R,
- ..Default::default()
- }
- }
+ /// Returns the channel.
+ fn channel(&self) -> Channel;
+}
- /// Constructs a new `FuncG` with empty properties.
- #[inline]
- pub fn new_g() -> Self {
- Self {
- channel: Channel::G,
- ..Default::default()
+macro_rules! func_x {
+ ($func_name:ident, $channel:expr) => {
+ pub struct $func_name {
+ channel: Channel,
+ function_type: FunctionType,
+ table_values: Vec<f64>,
+ slope: f64,
+ intercept: f64,
+ amplitude: f64,
+ exponent: f64,
+ offset: f64,
}
- }
- /// Constructs a new `FuncB` with empty properties.
- #[inline]
- pub fn new_b() -> Self {
- Self {
- channel: Channel::B,
- ..Default::default()
+ impl Default for $func_name {
+ #[inline]
+ fn default() -> Self {
+ Self {
+ channel: $channel,
+ function_type: FunctionType::Identity,
+ table_values: Vec::new(),
+ slope: 1.0,
+ intercept: 0.0,
+ amplitude: 1.0,
+ exponent: 1.0,
+ offset: 0.0,
+ }
+ }
}
- }
- /// Constructs a new `FuncA` with empty properties.
- #[inline]
- pub fn new_a() -> Self {
- Self {
- channel: Channel::A,
- ..Default::default()
- }
- }
+ impl ComponentTransferFunc for $func_name {
+ #[inline]
+ fn function_parameters(&self) -> FunctionParameters<'_> {
+ FunctionParameters {
+ table_values: &self.table_values,
+ slope: self.slope,
+ intercept: self.intercept,
+ amplitude: self.amplitude,
+ exponent: self.exponent,
+ offset: self.offset,
+ }
+ }
- /// Returns the component transfer function parameters.
- #[inline]
- fn function_parameters(&self) -> FunctionParameters<'_> {
- FunctionParameters {
- table_values: &self.table_values,
- slope: self.slope,
- intercept: self.intercept,
- amplitude: self.amplitude,
- exponent: self.exponent,
- offset: self.offset,
- }
- }
+ #[inline]
+ fn function(&self) -> Function {
+ match self.function_type {
+ FunctionType::Identity => identity,
+ FunctionType::Table => table,
+ FunctionType::Discrete => discrete,
+ FunctionType::Linear => linear,
+ FunctionType::Gamma => gamma,
+ }
+ }
- /// Returns the component transfer function.
- #[inline]
- fn function(&self) -> Function {
- match self.function_type {
- FunctionType::Identity => identity,
- FunctionType::Table => table,
- FunctionType::Discrete => discrete,
- FunctionType::Linear => linear,
- FunctionType::Gamma => gamma,
+ #[inline]
+ fn channel(&self) -> Channel {
+ self.channel
+ }
}
- }
-}
-
-impl NodeTrait for ComponentTransfer {
- impl_node_as_filter!();
-
- #[inline]
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
- self.base.set_atts(parent, pbag)
- }
-}
-impl NodeTrait for FuncX {
- #[inline]
- fn set_atts(&mut self, _parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
- for (attr, value) in pbag.iter() {
- match attr {
- local_name!("type") => self.function_type = FunctionType::parse(attr, value)?,
- local_name!("tableValues") => {
- let NumberList(v) = NumberList::parse_str(value, NumberListLength::Unbounded)
- .map_err(|err| {
- if let NumberListError::Parse(err) = err {
- NodeError::parse_error(attr, err)
- } else {
- panic!("unexpected number list error");
+ impl NodeTrait for $func_name {
+ #[inline]
+ fn set_atts(
+ &mut self,
+ _parent: Option<&RsvgNode>,
+ pbag: &PropertyBag<'_>,
+ ) -> NodeResult {
+ for (attr, value) in pbag.iter() {
+ match attr {
+ local_name!("type") => {
+ self.function_type = FunctionType::parse(attr, value)?
}
- })?;
- self.table_values = v;
- }
- local_name!("slope") => self.slope = parsers::number(value).attribute(attr)?,
- local_name!("intercept") => {
- self.intercept = parsers::number(value).attribute(attr)?
- }
- local_name!("amplitude") => {
- self.amplitude = parsers::number(value).attribute(attr)?
- }
- local_name!("exponent") => {
- self.exponent = parsers::number(value).attribute(attr)?
+ local_name!("tableValues") => {
+ let NumberList(v) =
+ NumberList::parse_str(value, NumberListLength::Unbounded).map_err(
+ |err| {
+ if let NumberListError::Parse(err) = err {
+ NodeError::parse_error(attr, err)
+ } else {
+ panic!("unexpected number list error");
+ }
+ },
+ )?;
+ self.table_values = v;
+ }
+ local_name!("slope") => {
+ self.slope = parsers::number(value).attribute(attr)?
+ }
+ local_name!("intercept") => {
+ self.intercept = parsers::number(value).attribute(attr)?
+ }
+ local_name!("amplitude") => {
+ self.amplitude = parsers::number(value).attribute(attr)?
+ }
+ local_name!("exponent") => {
+ self.exponent = parsers::number(value).attribute(attr)?
+ }
+ local_name!("offset") => {
+ self.offset = parsers::number(value).attribute(attr)?
+ }
+ _ => (),
+ }
}
- local_name!("offset") => self.offset = parsers::number(value).attribute(attr)?,
- _ => (),
- }
- }
- // 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;
+ }
+ }
+ _ => (),
}
+
+ Ok(())
}
- _ => (),
}
-
- Ok(())
- }
+ };
}
+// The `<feFuncR>` element
+func_x!(FuncR, Channel::R);
+
+// The `<feFuncG>` element
+func_x!(FuncG, Channel::G);
+
+// The `<feFuncB>` element
+func_x!(FuncB, Channel::B);
+
+// The `<feFuncA>` element
+func_x!(FuncA, Channel::A);
+
macro_rules! func_or_default {
- ($func_node:ident, $func_data:ident, $func_default:ident) => {
+ ($func_node:ident, $func_type:ty, $func_data:ident, $func_default:ident) => {
match $func_node {
Some(ref f) => {
$func_data = f.borrow();
- $func_data.get_impl::<FuncX>()
+ $func_data.get_impl::<$func_type>()
}
_ => &$func_default,
};
@@ -290,23 +311,20 @@ impl Filter for ComponentTransfer {
)?;
// Get a node for every pixel component.
- let get_node = |channel| {
+ fn get_node<F>(node: &RsvgNode, node_type: NodeType, channel: Channel) -> Option<RsvgNode>
+ where
+ F: ComponentTransferFunc + NodeTrait,
+ {
node.children()
.rev()
- .filter(|c| match c.borrow().get_type() {
- NodeType::ComponentTransferFunctionA
- | NodeType::ComponentTransferFunctionB
- | NodeType::ComponentTransferFunctionG
- | NodeType::ComponentTransferFunctionR => true,
- _ => false,
- })
- .find(|c| c.borrow().get_impl::<FuncX>().channel == channel)
+ .filter(|c| c.borrow().get_type() == node_type)
+ .find(|c| c.borrow().get_impl::<F>().channel() == channel)
};
- let func_r_node = get_node(Channel::R);
- let func_g_node = get_node(Channel::G);
- let func_b_node = get_node(Channel::B);
- let func_a_node = get_node(Channel::A);
+ let func_r_node = get_node::<FuncR>(node, NodeType::ComponentTransferFunctionR, Channel::R);
+ let func_g_node = get_node::<FuncG>(node, NodeType::ComponentTransferFunctionG, Channel::G);
+ let func_b_node = get_node::<FuncB>(node, NodeType::ComponentTransferFunctionB, Channel::B);
+ let func_a_node = get_node::<FuncA>(node, NodeType::ComponentTransferFunctionA, Channel::A);
for node in [&func_r_node, &func_g_node, &func_b_node, &func_a_node]
.iter()
@@ -317,8 +335,11 @@ impl Filter for ComponentTransfer {
}
}
- // This is the default node that performs an identity transformation.
- let func_default = FuncX::default();
+ // These are the default funcs that perform an identity transformation.
+ let func_r_default = FuncR::default();
+ let func_g_default = FuncG::default();
+ let func_b_default = FuncB::default();
+ let func_a_default = FuncA::default();
// We need to tell the borrow checker that these live long enough
let func_r_data;
@@ -326,13 +347,16 @@ impl Filter for ComponentTransfer {
let func_b_data;
let func_a_data;
- let func_r = func_or_default!(func_r_node, func_r_data, func_default);
- let func_g = func_or_default!(func_g_node, func_g_data, func_default);
- let func_b = func_or_default!(func_b_node, func_b_data, func_default);
- let func_a = func_or_default!(func_a_node, func_a_data, func_default);
+ let func_r = func_or_default!(func_r_node, FuncR, func_r_data, func_r_default);
+ let func_g = func_or_default!(func_g_node, FuncG, func_g_data, func_g_default);
+ let func_b = func_or_default!(func_b_node, FuncB, func_b_data, func_b_default);
+ let func_a = func_or_default!(func_a_node, FuncA, func_a_data, func_a_default);
#[inline]
- fn compute_func<'a>(func: &'a FuncX) -> impl Fn(u8, f64, f64) -> u8 + 'a {
+ fn compute_func<'a, F>(func: &'a F) -> impl Fn(u8, f64, f64) -> u8 + 'a
+ where
+ F: ComponentTransferFunc,
+ {
let compute = func.function();
let params = func.function_parameters();
@@ -348,9 +372,9 @@ impl Filter for ComponentTransfer {
}
}
- let compute_r = compute_func(&func_r);
- let compute_g = compute_func(&func_g);
- let compute_b = compute_func(&func_b);
+ let compute_r = compute_func::<FuncR>(&func_r);
+ let compute_g = compute_func::<FuncG>(&func_g);
+ let compute_b = compute_func::<FuncB>(&func_b);
// Alpha gets special handling since everything else depends on it.
let compute_a = func_a.function();
@@ -390,19 +414,3 @@ impl Filter for ComponentTransfer {
true
}
}
-
-impl FunctionType {
- fn parse(attr: LocalName, s: &str) -> Result<Self, NodeError> {
- match s {
- "identity" => Ok(FunctionType::Identity),
- "table" => Ok(FunctionType::Table),
- "discrete" => Ok(FunctionType::Discrete),
- "linear" => Ok(FunctionType::Linear),
- "gamma" => Ok(FunctionType::Gamma),
- _ => Err(NodeError::parse_error(
- attr,
- ParseError::new("invalid value"),
- )),
- }
- }
-}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]