[librsvg: 28/36] filters/convolve_matrix: remove interior mutability
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 28/36] filters/convolve_matrix: remove interior mutability
- Date: Mon, 1 Jul 2019 01:55:59 +0000 (UTC)
commit 8637dd555e394634e86226c7c7b391cbadd20fbf
Author: Paolo Borelli <pborelli gnome org>
Date: Sun Jun 30 16:57:40 2019 +0200
filters/convolve_matrix: remove interior mutability
rsvg_internals/src/filters/convolve_matrix.rs | 198 +++++++++++++-------------
1 file changed, 97 insertions(+), 101 deletions(-)
---
diff --git a/rsvg_internals/src/filters/convolve_matrix.rs b/rsvg_internals/src/filters/convolve_matrix.rs
index d67ca855..c2867e74 100644
--- a/rsvg_internals/src/filters/convolve_matrix.rs
+++ b/rsvg_internals/src/filters/convolve_matrix.rs
@@ -1,5 +1,3 @@
-use std::cell::{Cell, RefCell};
-
use cairo::{self, ImageSurface, MatrixTrait};
use markup5ever::{local_name, LocalName};
use nalgebra::{DMatrix, Dynamic, VecStorage};
@@ -26,15 +24,15 @@ use super::{Filter, FilterError, PrimitiveWithInput};
/// The `feConvolveMatrix` filter primitive.
pub struct ConvolveMatrix {
base: PrimitiveWithInput,
- order: Cell<(u32, u32)>,
- kernel_matrix: RefCell<Option<DMatrix<f64>>>,
- divisor: Cell<Option<f64>>,
- bias: Cell<f64>,
- target_x: Cell<Option<u32>>,
- target_y: Cell<Option<u32>>,
- edge_mode: Cell<EdgeMode>,
- kernel_unit_length: Cell<Option<(f64, f64)>>,
- preserve_alpha: Cell<bool>,
+ order: (u32, u32),
+ kernel_matrix: Option<DMatrix<f64>>,
+ divisor: Option<f64>,
+ bias: f64,
+ target_x: Option<u32>,
+ target_y: Option<u32>,
+ edge_mode: EdgeMode,
+ kernel_unit_length: Option<(f64, f64)>,
+ preserve_alpha: bool,
}
impl Default for ConvolveMatrix {
@@ -43,15 +41,15 @@ impl Default for ConvolveMatrix {
fn default() -> ConvolveMatrix {
ConvolveMatrix {
base: PrimitiveWithInput::new::<Self>(),
- order: Cell::new((3, 3)),
- kernel_matrix: RefCell::new(None),
- divisor: Cell::new(None),
- bias: Cell::new(0.0),
- target_x: Cell::new(None),
- target_y: Cell::new(None),
- edge_mode: Cell::new(EdgeMode::Duplicate),
- kernel_unit_length: Cell::new(None),
- preserve_alpha: Cell::new(false),
+ order: (3, 3),
+ kernel_matrix: None,
+ divisor: None,
+ bias: 0.0,
+ target_x: None,
+ target_y: None,
+ edge_mode: EdgeMode::Duplicate,
+ kernel_unit_length: None,
+ preserve_alpha: false,
}
}
}
@@ -64,8 +62,8 @@ impl NodeTrait for ConvolveMatrix {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("order") => self.order.set(
- parsers::integer_optional_integer(value)
+ local_name!("order") => {
+ self.order = parsers::integer_optional_integer(value)
.attribute(attr.clone())
.and_then(|(x, y)| {
if x > 0 && y > 0 {
@@ -76,47 +74,49 @@ impl NodeTrait for ConvolveMatrix {
"values must be greater than 0",
))
}
- })?,
- ),
- local_name!("divisor") => self.divisor.set(Some(
- parsers::number(value)
- .attribute(attr.clone())
- .and_then(|x| {
+ })?
+ }
+ local_name!("divisor") => {
+ self.divisor = Some(parsers::number(value).attribute(attr.clone()).and_then(
+ |x| {
if x != 0.0 {
Ok(x)
} else {
Err(NodeError::value_error(attr, "divisor cannot be equal to 0"))
}
- })?,
- )),
- local_name!("bias") => self.bias.set(
- parsers::number(value).attribute(attr)?,
- ),
- local_name!("edgeMode") => self.edge_mode.set(EdgeMode::parse(attr, value)?),
- local_name!("kernelUnitLength") => self.kernel_unit_length.set(Some(
- parsers::number_optional_number(value)
- .attribute(attr.clone())
- .and_then(|(x, y)| {
- if x > 0.0 && y > 0.0 {
- Ok((x, y))
- } else {
- Err(NodeError::value_error(
- attr,
- "kernelUnitLength can't be less or equal to zero",
- ))
- }
- })?,
- )),
- local_name!("preserveAlpha") => self.preserve_alpha.set(match value {
- "false" => false,
- "true" => true,
- _ => {
- return Err(NodeError::parse_error(
- attr,
- ParseError::new("expected false or true"),
- ));
+ },
+ )?)
+ }
+ local_name!("bias") => self.bias = parsers::number(value).attribute(attr)?,
+ local_name!("edgeMode") => self.edge_mode = EdgeMode::parse(attr, value)?,
+ local_name!("kernelUnitLength") => {
+ self.kernel_unit_length = Some(
+ parsers::number_optional_number(value)
+ .attribute(attr.clone())
+ .and_then(|(x, y)| {
+ if x > 0.0 && y > 0.0 {
+ Ok((x, y))
+ } else {
+ Err(NodeError::value_error(
+ attr,
+ "kernelUnitLength can't be less or equal to zero",
+ ))
+ }
+ })?,
+ )
+ }
+ local_name!("preserveAlpha") => {
+ self.preserve_alpha = match value {
+ "false" => false,
+ "true" => true,
+ _ => {
+ return Err(NodeError::parse_error(
+ attr,
+ ParseError::new("expected false or true"),
+ ));
+ }
}
- }),
+ }
_ => (),
}
}
@@ -124,11 +124,10 @@ impl NodeTrait for ConvolveMatrix {
// target_x and target_y depend on order.
for (attr, value) in pbag.iter() {
match attr {
- local_name!("targetX") => self.target_x.set(Some(
- parsers::integer(value)
- .attribute(attr.clone())
- .and_then(|x| {
- if x >= 0 && x < self.order.get().0 as i32 {
+ local_name!("targetX") => {
+ self.target_x = Some(parsers::integer(value).attribute(attr.clone()).and_then(
+ |x| {
+ if x >= 0 && x < self.order.0 as i32 {
Ok(x as u32)
} else {
Err(NodeError::value_error(
@@ -136,13 +135,13 @@ impl NodeTrait for ConvolveMatrix {
"targetX must be greater or equal to zero and less than orderX",
))
}
- })?,
- )),
- local_name!("targetY") => self.target_y.set(Some(
- parsers::integer(value)
- .attribute(attr.clone())
- .and_then(|x| {
- if x >= 0 && x < self.order.get().1 as i32 {
+ },
+ )?)
+ }
+ local_name!("targetY") => {
+ self.target_y = Some(parsers::integer(value).attribute(attr.clone()).and_then(
+ |x| {
+ if x >= 0 && x < self.order.1 as i32 {
Ok(x as u32)
} else {
Err(NodeError::value_error(
@@ -150,18 +149,19 @@ impl NodeTrait for ConvolveMatrix {
"targetY must be greater or equal to zero and less than orderY",
))
}
- })?,
- )),
+ },
+ )?)
+ }
_ => (),
}
}
// Default values for target_x and target_y.
- if self.target_x.get().is_none() {
- self.target_x.set(Some(self.order.get().0 / 2));
+ if self.target_x.is_none() {
+ self.target_x = Some(self.order.0 / 2);
}
- if self.target_y.get().is_none() {
- self.target_y.set(Some(self.order.get().1 / 2));
+ if self.target_y.is_none() {
+ self.target_y = Some(self.order.1 / 2);
}
// Finally, parse the kernel matrix.
@@ -169,8 +169,8 @@ impl NodeTrait for ConvolveMatrix {
.iter()
.filter(|(attr, _)| *attr == local_name!("kernelMatrix"))
{
- self.kernel_matrix.replace(Some({
- let number_of_elements = self.order.get().0 as usize * self.order.get().1 as usize;
+ self.kernel_matrix = Some({
+ let number_of_elements = self.order.0 as usize * self.order.1 as usize;
// #352: Parse as an unbounded list rather than exact length to prevent aborts due
// to huge allocation attempts by underlying Vec::with_capacity().
@@ -196,15 +196,15 @@ impl NodeTrait for ConvolveMatrix {
}
DMatrix::from_data(VecStorage::new(
- Dynamic::new(self.order.get().1 as usize),
- Dynamic::new(self.order.get().0 as usize),
+ Dynamic::new(self.order.1 as usize),
+ Dynamic::new(self.order.0 as usize),
v,
))
- }));
+ });
}
// kernel_matrix must have been specified.
- if self.kernel_matrix.borrow().is_none() {
+ if self.kernel_matrix.is_none() {
return Err(NodeError::value_error(
local_name!("kernelMatrix"),
"the value must be set",
@@ -212,13 +212,11 @@ impl NodeTrait for ConvolveMatrix {
}
// Default value for the divisor.
- if self.divisor.get().is_none() {
- self.divisor.set(Some(
- self.kernel_matrix.borrow().as_ref().unwrap().iter().sum(),
- ));
+ if self.divisor.is_none() {
+ self.divisor = Some(self.kernel_matrix.as_ref().unwrap().iter().sum());
- if self.divisor.get().unwrap() == 0.0 {
- self.divisor.set(Some(1.0));
+ if self.divisor.unwrap() == 0.0 {
+ self.divisor = Some(1.0);
}
}
@@ -241,7 +239,7 @@ impl Filter for ConvolveMatrix {
.into_irect(draw_ctx);
let original_bounds = bounds;
- let mut input_surface = if self.preserve_alpha.get() {
+ let mut input_surface = if self.preserve_alpha {
// preserve_alpha means we need to premultiply and unpremultiply the values.
input.surface().unpremultiply(bounds)?
} else {
@@ -250,7 +248,6 @@ impl Filter for ConvolveMatrix {
let scale = self
.kernel_unit_length
- .get()
.map(|(dx, dy)| ctx.paffine().transform_distance(dx, dy));
if let Some((ox, oy)) = scale {
@@ -261,8 +258,7 @@ impl Filter for ConvolveMatrix {
bounds = new_bounds;
}
- let matrix = self.kernel_matrix.borrow();
- let matrix = matrix.as_ref().unwrap();
+ let matrix = self.kernel_matrix.as_ref().unwrap();
let mut output_surface = ImageSurface::create(
cairo::Format::ARgb32,
@@ -277,10 +273,10 @@ impl Filter for ConvolveMatrix {
for (x, y, pixel) in Pixels::new(&input_surface, bounds) {
// Compute the convolution rectangle bounds.
let kernel_bounds = IRect {
- x0: x as i32 - self.target_x.get().unwrap() as i32,
- y0: y as i32 - self.target_y.get().unwrap() as i32,
- x1: x as i32 - self.target_x.get().unwrap() as i32 + self.order.get().0 as i32,
- y1: y as i32 - self.target_y.get().unwrap() as i32 + self.order.get().1 as i32,
+ x0: x as i32 - self.target_x.unwrap() as i32,
+ y0: y as i32 - self.target_y.unwrap() as i32,
+ x1: x as i32 - self.target_x.unwrap() as i32 + self.order.0 as i32,
+ y1: y as i32 - self.target_y.unwrap() as i32 + self.order.1 as i32,
};
// Do the convolution.
@@ -290,7 +286,7 @@ impl Filter for ConvolveMatrix {
let mut a = 0.0;
for (x, y, pixel) in
- PixelRectangle::new(&input_surface, bounds, kernel_bounds, self.edge_mode.get())
+ PixelRectangle::new(&input_surface, bounds, kernel_bounds, self.edge_mode)
{
let kernel_x = (kernel_bounds.x1 - x - 1) as usize;
let kernel_y = (kernel_bounds.y1 - y - 1) as usize;
@@ -299,24 +295,24 @@ impl Filter for ConvolveMatrix {
g += f64::from(pixel.g) / 255.0 * matrix[(kernel_y, kernel_x)];
b += f64::from(pixel.b) / 255.0 * matrix[(kernel_y, kernel_x)];
- if !self.preserve_alpha.get() {
+ if !self.preserve_alpha {
a += f64::from(pixel.a) / 255.0 * matrix[(kernel_y, kernel_x)];
}
}
// If preserve_alpha is true, set a to the source alpha value.
- if self.preserve_alpha.get() {
+ if self.preserve_alpha {
a = f64::from(pixel.a) / 255.0;
} else {
- a = a / self.divisor.get().unwrap() + self.bias.get();
+ a = a / self.divisor.unwrap() + self.bias;
}
let clamped_a = clamp(a, 0.0, 1.0);
let compute = |x| {
- let x = x / self.divisor.get().unwrap() + self.bias.get() * a;
+ let x = x / self.divisor.unwrap() + self.bias * a;
- let x = if self.preserve_alpha.get() {
+ let x = if self.preserve_alpha {
// Premultiply the output value.
clamp(x, 0.0, 1.0) * clamped_a
} else {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]