summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@gnome.org>2019-06-30 20:48:26 -0500
committerFederico Mena Quintero <federico@gnome.org>2019-06-30 20:48:26 -0500
commit2a83c10796ed4c7c25afe34769ae895dd01d7d96 (patch)
tree19158efb98a21698f143f4e61866125391c00d5d
parentfd24ae31a234f28891b6bdf53867d73cebeeeb64 (diff)
parentfc37026246bc521813fe62d8b783b0c2f8678a22 (diff)
downloadlibrsvg-2a83c10796ed4c7c25afe34769ae895dd01d7d96.tar.gz
Merge branch 'pborelli/librsvg-nointeriomut'
-rw-r--r--rsvg_internals/src/clip_path.rs16
-rw-r--r--rsvg_internals/src/filters/blend.rs22
-rw-r--r--rsvg_internals/src/filters/color_matrix.rs24
-rw-r--r--rsvg_internals/src/filters/component_transfer.rs91
-rw-r--r--rsvg_internals/src/filters/composite.rs71
-rw-r--r--rsvg_internals/src/filters/context.rs6
-rw-r--r--rsvg_internals/src/filters/convolve_matrix.rs202
-rw-r--r--rsvg_internals/src/filters/displacement_map.rs52
-rw-r--r--rsvg_internals/src/filters/flood.rs4
-rw-r--r--rsvg_internals/src/filters/gaussian_blur.rs19
-rw-r--r--rsvg_internals/src/filters/image.rs28
-rw-r--r--rsvg_internals/src/filters/light/light_source.rs138
-rw-r--r--rsvg_internals/src/filters/light/lighting.rs142
-rw-r--r--rsvg_internals/src/filters/merge.rs18
-rw-r--r--rsvg_internals/src/filters/mod.rs83
-rw-r--r--rsvg_internals/src/filters/morphology.rs31
-rw-r--r--rsvg_internals/src/filters/node.rs80
-rw-r--r--rsvg_internals/src/filters/offset.rs27
-rw-r--r--rsvg_internals/src/filters/tile.rs4
-rw-r--r--rsvg_internals/src/filters/turbulence.rs65
-rw-r--r--rsvg_internals/src/gradient.rs434
-rw-r--r--rsvg_internals/src/image.rs52
-rw-r--r--rsvg_internals/src/link.rs12
-rw-r--r--rsvg_internals/src/marker.rs89
-rw-r--r--rsvg_internals/src/mask.rs62
-rw-r--r--rsvg_internals/src/node.rs2
-rw-r--r--rsvg_internals/src/pattern.rs82
-rw-r--r--rsvg_internals/src/shapes.rs168
-rw-r--r--rsvg_internals/src/structure.rs142
-rw-r--r--rsvg_internals/src/style.rs15
-rw-r--r--rsvg_internals/src/text.rs79
31 files changed, 1011 insertions, 1249 deletions
diff --git a/rsvg_internals/src/clip_path.rs b/rsvg_internals/src/clip_path.rs
index a2d72311..b6ad0c20 100644
--- a/rsvg_internals/src/clip_path.rs
+++ b/rsvg_internals/src/clip_path.rs
@@ -1,5 +1,3 @@
-use std::cell::Cell;
-
use cairo::{self, MatrixTrait};
use markup5ever::local_name;
@@ -15,12 +13,12 @@ coord_units!(ClipPathUnits, CoordUnits::UserSpaceOnUse);
#[derive(Default)]
pub struct NodeClipPath {
- units: Cell<ClipPathUnits>,
+ units: ClipPathUnits,
}
impl NodeClipPath {
pub fn get_units(&self) -> ClipPathUnits {
- self.units.get()
+ self.units
}
pub fn to_cairo_context(
@@ -29,9 +27,7 @@ impl NodeClipPath {
draw_ctx: &mut DrawingCtx,
bbox: &BoundingBox,
) -> Result<(), RenderingError> {
- let clip_units = self.units.get();
-
- if clip_units == ClipPathUnits(CoordUnits::ObjectBoundingBox) && bbox.rect.is_none() {
+ if self.units == ClipPathUnits(CoordUnits::ObjectBoundingBox) && bbox.rect.is_none() {
// The node being clipped is empty / doesn't have a
// bounding box, so there's nothing to clip!
return Ok(());
@@ -42,7 +38,7 @@ impl NodeClipPath {
draw_ctx.with_saved_matrix(&mut |dc| {
let cr = dc.get_cairo_context();
- if clip_units == ClipPathUnits(CoordUnits::ObjectBoundingBox) {
+ if self.units == ClipPathUnits(CoordUnits::ObjectBoundingBox) {
let bbox_rect = bbox.rect.as_ref().unwrap();
cr.transform(cairo::Matrix::new(
@@ -65,10 +61,10 @@ impl NodeClipPath {
}
impl NodeTrait for NodeClipPath {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("clipPathUnits") => self.units.set(attr.parse(value)?),
+ local_name!("clipPathUnits") => self.units = attr.parse(value)?,
_ => (),
}
}
diff --git a/rsvg_internals/src/filters/blend.rs b/rsvg_internals/src/filters/blend.rs
index 754f6835..6075e78e 100644
--- a/rsvg_internals/src/filters/blend.rs
+++ b/rsvg_internals/src/filters/blend.rs
@@ -1,5 +1,3 @@
-use std::cell::{Cell, RefCell};
-
use cairo;
use markup5ever::{local_name, LocalName};
@@ -27,8 +25,8 @@ enum Mode {
/// The `feBlend` filter primitive.
pub struct Blend {
base: PrimitiveWithInput,
- in2: RefCell<Option<Input>>,
- mode: Cell<Mode>,
+ in2: Option<Input>,
+ mode: Mode,
}
impl Default for Blend {
@@ -37,8 +35,8 @@ impl Default for Blend {
fn default() -> Blend {
Blend {
base: PrimitiveWithInput::new::<Self>(),
- in2: RefCell::new(None),
- mode: Cell::new(Mode::Normal),
+ in2: None,
+ mode: Mode::Normal,
}
}
}
@@ -46,15 +44,15 @@ impl Default for Blend {
impl NodeTrait for Blend {
impl_node_as_filter!();
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
local_name!("in2") => {
- self.in2.replace(Some(Input::parse(attr, value)?));
+ self.in2 = Some(Input::parse(attr, value)?);
}
- local_name!("mode") => self.mode.set(Mode::parse(attr, value)?),
+ local_name!("mode") => self.mode = Mode::parse(attr, value)?,
_ => (),
}
}
@@ -71,7 +69,7 @@ impl Filter for Blend {
draw_ctx: &mut DrawingCtx,
) -> Result<FilterResult, FilterError> {
let input = self.base.get_input(ctx, draw_ctx)?;
- let input_2 = ctx.get_input(draw_ctx, self.in2.borrow().as_ref())?;
+ let input_2 = ctx.get_input(draw_ctx, self.in2.as_ref())?;
let bounds = self
.base
.get_bounds(ctx)
@@ -108,12 +106,12 @@ impl Filter for Blend {
cr.clip();
input.surface().set_as_source_surface(&cr, 0f64, 0f64);
- cr.set_operator(self.mode.get().into());
+ cr.set_operator(self.mode.into());
cr.paint();
}
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: SharedImageSurface::new(output_surface, surface_type)?,
bounds,
diff --git a/rsvg_internals/src/filters/color_matrix.rs b/rsvg_internals/src/filters/color_matrix.rs
index 2381f321..de9de6f7 100644
--- a/rsvg_internals/src/filters/color_matrix.rs
+++ b/rsvg_internals/src/filters/color_matrix.rs
@@ -1,5 +1,3 @@
-use std::cell::RefCell;
-
use cairo::{self, ImageSurface};
use markup5ever::{local_name, LocalName};
use nalgebra::{Matrix3, Matrix4x5, Matrix5, Vector5};
@@ -33,7 +31,7 @@ enum OperationType {
/// The `feColorMatrix` filter primitive.
pub struct ColorMatrix {
base: PrimitiveWithInput,
- matrix: RefCell<Matrix5<f64>>,
+ matrix: Matrix5<f64>,
}
impl Default for ColorMatrix {
@@ -42,7 +40,7 @@ impl Default for ColorMatrix {
fn default() -> ColorMatrix {
ColorMatrix {
base: PrimitiveWithInput::new::<Self>(),
- matrix: RefCell::new(Matrix5::identity()),
+ matrix: Matrix5::identity(),
}
}
}
@@ -50,7 +48,7 @@ impl Default for ColorMatrix {
impl NodeTrait for ColorMatrix {
impl_node_as_filter!();
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)?;
// First, determine the operation type.
@@ -62,16 +60,16 @@ impl NodeTrait for ColorMatrix {
// Now read the matrix correspondingly.
// LuminanceToAlpha doesn't accept any matrix.
if operation_type == OperationType::LuminanceToAlpha {
- #[cfg_attr(rustfmt, rustfmt_skip)]
- self.matrix.replace(
+ self.matrix = {
+ #[cfg_attr(rustfmt, rustfmt_skip)]
Matrix5::new(
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.2125, 0.7154, 0.0721, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 1.0,
- ),
- );
+ )
+ };
} else {
for (attr, value) in pbag
.iter()
@@ -152,7 +150,7 @@ impl NodeTrait for ColorMatrix {
}
};
- self.matrix.replace(new_matrix);
+ self.matrix = new_matrix;
}
}
@@ -174,8 +172,6 @@ impl Filter for ColorMatrix {
.add_input(&input)
.into_irect(draw_ctx);
- let matrix = &*self.matrix.borrow();
-
let mut output_surface = ImageSurface::create(
cairo::Format::ARgb32,
ctx.source_graphic().width(),
@@ -201,7 +197,7 @@ impl Filter for ColorMatrix {
)
};
let mut new_pixel_vec = Vector5::zeros();
- matrix.mul_to(&pixel_vec, &mut new_pixel_vec);
+ self.matrix.mul_to(&pixel_vec, &mut new_pixel_vec);
let new_alpha = clamp(new_pixel_vec[3], 0.0, 1.0);
@@ -219,7 +215,7 @@ impl Filter for ColorMatrix {
}
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: SharedImageSurface::new(output_surface, input.surface().surface_type())?,
bounds,
diff --git a/rsvg_internals/src/filters/component_transfer.rs b/rsvg_internals/src/filters/component_transfer.rs
index 941c1e1c..a18f01da 100644
--- a/rsvg_internals/src/filters/component_transfer.rs
+++ b/rsvg_internals/src/filters/component_transfer.rs
@@ -1,4 +1,3 @@
-use std::cell::{Cell, Ref, RefCell};
use std::cmp::min;
use cairo::{self, ImageSurface};
@@ -48,18 +47,18 @@ enum FunctionType {
/// The `<feFuncX>` element (X is R, G, B or A).
pub struct FuncX {
channel: Channel,
- function_type: Cell<FunctionType>,
- table_values: RefCell<Vec<f64>>,
- slope: Cell<f64>,
- intercept: Cell<f64>,
- amplitude: Cell<f64>,
- exponent: Cell<f64>,
- offset: Cell<f64>,
+ function_type: FunctionType,
+ table_values: Vec<f64>,
+ slope: f64,
+ intercept: f64,
+ amplitude: f64,
+ exponent: f64,
+ offset: f64,
}
/// The compute function parameters.
struct FunctionParameters<'a> {
- table_values: Ref<'a, Vec<f64>>,
+ table_values: &'a Vec<f64>,
slope: f64,
intercept: f64,
amplitude: f64,
@@ -127,13 +126,13 @@ impl Default for FuncX {
fn default() -> Self {
Self {
channel: Channel::R,
- function_type: Cell::new(FunctionType::Identity),
- table_values: RefCell::new(Vec::new()),
- slope: Cell::new(1f64),
- intercept: Cell::new(0f64),
- amplitude: Cell::new(1f64),
- exponent: Cell::new(1f64),
- offset: Cell::new(0f64),
+ function_type: FunctionType::Identity,
+ table_values: Vec::new(),
+ slope: 1.0,
+ intercept: 0.0,
+ amplitude: 1.0,
+ exponent: 1.0,
+ offset: 0.0,
}
}
}
@@ -179,19 +178,19 @@ impl FuncX {
#[inline]
fn function_parameters(&self) -> FunctionParameters<'_> {
FunctionParameters {
- table_values: self.table_values.borrow(),
- slope: self.slope.get(),
- intercept: self.intercept.get(),
- amplitude: self.amplitude.get(),
- exponent: self.exponent.get(),
- offset: self.offset.get(),
+ 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.
#[inline]
fn function(&self) -> Function {
- match self.function_type.get() {
+ match self.function_type {
FunctionType::Identity => identity,
FunctionType::Table => table,
FunctionType::Discrete => discrete,
@@ -205,17 +204,17 @@ impl NodeTrait for ComponentTransfer {
impl_node_as_filter!();
#[inline]
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ 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(&self, _parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ 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.set(FunctionType::parse(attr, value)?),
+ 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| {
@@ -225,33 +224,29 @@ impl NodeTrait for FuncX {
panic!("unexpected number list error");
}
})?;
- self.table_values.replace(v);
+ 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!("slope") => self.slope.set(
- parsers::number(value).attribute(attr)?,
- ),
- local_name!("intercept") => self.intercept.set(
- parsers::number(value).attribute(attr)?,
- ),
- local_name!("amplitude") => self.amplitude.set(
- parsers::number(value).attribute(attr)?,
- ),
- local_name!("exponent") => self.exponent.set(
- parsers::number(value).attribute(attr)?,
- ),
- local_name!("offset") => self.offset.set(
- 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.get() {
+ // 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.borrow().is_empty() {
- self.function_type.set(FunctionType::Identity);
+ if self.table_values.is_empty() {
+ self.function_type = FunctionType::Identity;
}
}
_ => (),
@@ -383,7 +378,7 @@ impl Filter for ComponentTransfer {
}
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: SharedImageSurface::new(output_surface, input.surface().surface_type())?,
bounds,
diff --git a/rsvg_internals/src/filters/composite.rs b/rsvg_internals/src/filters/composite.rs
index c0432507..b42701ac 100644
--- a/rsvg_internals/src/filters/composite.rs
+++ b/rsvg_internals/src/filters/composite.rs
@@ -1,5 +1,3 @@
-use std::cell::{Cell, RefCell};
-
use cairo::{self, ImageSurface};
use cssparser::{CowRcStr, Parser, Token};
use markup5ever::local_name;
@@ -36,12 +34,12 @@ enum Operator {
/// The `feComposite` filter primitive.
pub struct Composite {
base: PrimitiveWithInput,
- in2: RefCell<Option<Input>>,
- operator: Cell<Operator>,
- k1: Cell<f64>,
- k2: Cell<f64>,
- k3: Cell<f64>,
- k4: Cell<f64>,
+ in2: Option<Input>,
+ operator: Operator,
+ k1: f64,
+ k2: f64,
+ k3: f64,
+ k4: f64,
}
impl Default for Composite {
@@ -50,12 +48,12 @@ impl Default for Composite {
fn default() -> Composite {
Composite {
base: PrimitiveWithInput::new::<Self>(),
- in2: RefCell::new(None),
- operator: Cell::new(Operator::Over),
- k1: Cell::new(0f64),
- k2: Cell::new(0f64),
- k3: Cell::new(0f64),
- k4: Cell::new(0f64),
+ in2: None,
+ operator: Operator::Over,
+ k1: 0.0,
+ k2: 0.0,
+ k3: 0.0,
+ k4: 0.0,
}
}
}
@@ -63,27 +61,17 @@ impl Default for Composite {
impl NodeTrait for Composite {
impl_node_as_filter!();
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
- local_name!("in2") => {
- self.in2.replace(Some(Input::parse(attr, value)?));
- }
- local_name!("operator") => self.operator.set(attr.parse(value)?),
- local_name!("k1") => self.k1.set(
- parsers::number(value).attribute(attr)?,
- ),
- local_name!("k2") => self.k2.set(
- parsers::number(value).attribute(attr)?,
- ),
- local_name!("k3") => self.k3.set(
- parsers::number(value).attribute(attr)?,
- ),
- local_name!("k4") => self.k4.set(
- parsers::number(value).attribute(attr)?,
- ),
+ local_name!("in2") => self.in2 = Some(Input::parse(attr, value)?),
+ local_name!("operator") => self.operator = attr.parse(value)?,
+ local_name!("k1") => self.k1 = parsers::number(value).attribute(attr)?,
+ local_name!("k2") => self.k2 = parsers::number(value).attribute(attr)?,
+ local_name!("k3") => self.k3 = parsers::number(value).attribute(attr)?,
+ local_name!("k4") => self.k4 = parsers::number(value).attribute(attr)?,
_ => (),
}
}
@@ -149,7 +137,7 @@ impl Filter for Composite {
draw_ctx: &mut DrawingCtx,
) -> Result<FilterResult, FilterError> {
let input = self.base.get_input(ctx, draw_ctx)?;
- let input_2 = ctx.get_input(draw_ctx, self.in2.borrow().as_ref())?;
+ let input_2 = ctx.get_input(draw_ctx, self.in2.as_ref())?;
let bounds = self
.base
.get_bounds(ctx)
@@ -174,27 +162,22 @@ impl Filter for Composite {
input.surface().surface_type()
};
- let output_surface = if self.operator.get() == Operator::Arithmetic {
+ let output_surface = if self.operator == Operator::Arithmetic {
let mut output_surface = ImageSurface::create(
cairo::Format::ARgb32,
input.surface().width(),
input.surface().height(),
)?;
- let k1 = self.k1.get();
- let k2 = self.k2.get();
- let k3 = self.k3.get();
- let k4 = self.k4.get();
-
composite_arithmetic(
input.surface(),
input_2.surface(),
&mut output_surface,
bounds,
- k1,
- k2,
- k3,
- k4,
+ self.k1,
+ self.k2,
+ self.k3,
+ self.k4,
);
output_surface
@@ -211,14 +194,14 @@ impl Filter for Composite {
cr.clip();
input.surface().set_as_source_surface(&cr, 0f64, 0f64);
- cr.set_operator(self.operator.get().into());
+ cr.set_operator(self.operator.into());
cr.paint();
output_surface
};
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: SharedImageSurface::new(output_surface, surface_type)?,
bounds,
diff --git a/rsvg_internals/src/filters/context.rs b/rsvg_internals/src/filters/context.rs
index 477611be..4a5d2e77 100644
--- a/rsvg_internals/src/filters/context.rs
+++ b/rsvg_internals/src/filters/context.rs
@@ -117,7 +117,7 @@ impl FilterContext {
let node_data = filter_node.borrow();
let filter = node_data.get_impl::<NodeFilter>();
- let affine = match filter.filterunits.get() {
+ let affine = match filter.filterunits {
CoordUnits::UserSpaceOnUse => cr_affine,
CoordUnits::ObjectBoundingBox => {
let affine = cairo::Matrix::new(
@@ -132,7 +132,7 @@ impl FilterContext {
}
};
- let paffine = match filter.primitiveunits.get() {
+ let paffine = match filter.primitiveunits {
CoordUnits::UserSpaceOnUse => cr_affine,
CoordUnits::ObjectBoundingBox => {
let affine = cairo::Matrix::new(
@@ -310,7 +310,7 @@ impl FilterContext {
let filter = node_data.get_impl::<NodeFilter>();
// See comments in compute_effects_region() for how this works.
- if filter.primitiveunits.get() == CoordUnits::ObjectBoundingBox {
+ if filter.primitiveunits == CoordUnits::ObjectBoundingBox {
draw_ctx.push_view_box(1.0, 1.0)
} else {
draw_ctx.get_view_params()
diff --git a/rsvg_internals/src/filters/convolve_matrix.rs b/rsvg_internals/src/filters/convolve_matrix.rs
index a5d22026..d5ce1f17 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,
}
}
}
@@ -59,13 +57,13 @@ impl Default for ConvolveMatrix {
impl NodeTrait for ConvolveMatrix {
impl_node_as_filter!();
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)?;
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 {
@@ -354,7 +350,7 @@ impl Filter for ConvolveMatrix {
}
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: output_surface,
bounds,
diff --git a/rsvg_internals/src/filters/displacement_map.rs b/rsvg_internals/src/filters/displacement_map.rs
index b6220da4..b6c581cd 100644
--- a/rsvg_internals/src/filters/displacement_map.rs
+++ b/rsvg_internals/src/filters/displacement_map.rs
@@ -1,5 +1,3 @@
-use std::cell::{Cell, RefCell};
-
use cairo::{self, ImageSurface, MatrixTrait};
use markup5ever::{local_name, LocalName};
@@ -25,10 +23,10 @@ enum ColorChannel {
/// The `feDisplacementMap` filter primitive.
pub struct DisplacementMap {
base: PrimitiveWithInput,
- in2: RefCell<Option<Input>>,
- scale: Cell<f64>,
- x_channel_selector: Cell<ColorChannel>,
- y_channel_selector: Cell<ColorChannel>,
+ in2: Option<Input>,
+ scale: f64,
+ x_channel_selector: ColorChannel,
+ y_channel_selector: ColorChannel,
}
impl Default for DisplacementMap {
@@ -37,10 +35,10 @@ impl Default for DisplacementMap {
fn default() -> DisplacementMap {
DisplacementMap {
base: PrimitiveWithInput::new::<Self>(),
- in2: RefCell::new(None),
- scale: Cell::new(0.0),
- x_channel_selector: Cell::new(ColorChannel::A),
- y_channel_selector: Cell::new(ColorChannel::A),
+ in2: None,
+ scale: 0.0,
+ x_channel_selector: ColorChannel::A,
+ y_channel_selector: ColorChannel::A,
}
}
}
@@ -48,23 +46,19 @@ impl Default for DisplacementMap {
impl NodeTrait for DisplacementMap {
impl_node_as_filter!();
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
- local_name!("in2") => {
- self.in2.replace(Some(Input::parse(attr, value)?));
+ local_name!("in2") => self.in2 = Some(Input::parse(attr, value)?),
+ local_name!("scale") => self.scale = parsers::number(value).attribute(attr)?,
+ local_name!("xChannelSelector") => {
+ self.x_channel_selector = ColorChannel::parse(attr, value)?
+ }
+ local_name!("yChannelSelector") => {
+ self.y_channel_selector = ColorChannel::parse(attr, value)?
}
- local_name!("scale") => self.scale.set(
- parsers::number(value).attribute(attr)?,
- ),
- local_name!("xChannelSelector") => self
- .x_channel_selector
- .set(ColorChannel::parse(attr, value)?),
- local_name!("yChannelSelector") => self
- .y_channel_selector
- .set(ColorChannel::parse(attr, value)?),
_ => (),
}
}
@@ -81,7 +75,7 @@ impl Filter for DisplacementMap {
draw_ctx: &mut DrawingCtx,
) -> Result<FilterResult, FilterError> {
let input = self.base.get_input(ctx, draw_ctx)?;
- let displacement_input = ctx.get_input(draw_ctx, self.in2.borrow().as_ref())?;
+ let displacement_input = ctx.get_input(draw_ctx, self.in2.as_ref())?;
let bounds = self
.base
.get_bounds(ctx)
@@ -92,11 +86,7 @@ impl Filter for DisplacementMap {
// Displacement map's values need to be non-premultiplied.
let displacement_surface = displacement_input.surface().unpremultiply(bounds)?;
- let scale = self.scale.get();
- let (sx, sy) = ctx.paffine().transform_distance(scale, scale);
-
- let x_channel = self.x_channel_selector.get();
- let y_channel = self.y_channel_selector.get();
+ let (sx, sy) = ctx.paffine().transform_distance(self.scale, self.scale);
let output_surface = ImageSurface::create(
cairo::Format::ARgb32,
@@ -117,8 +107,8 @@ impl Filter for DisplacementMap {
let process = |x| f64::from(x) / 255.0 - 0.5;
- let dx = process(get_value(x_channel));
- let dy = process(get_value(y_channel));
+ let dx = process(get_value(self.x_channel_selector));
+ let dy = process(get_value(self.y_channel_selector));
let x = f64::from(x);
let y = f64::from(y);
@@ -137,7 +127,7 @@ impl Filter for DisplacementMap {
}
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: SharedImageSurface::new(output_surface, input.surface().surface_type())?,
bounds,
diff --git a/rsvg_internals/src/filters/flood.rs b/rsvg_internals/src/filters/flood.rs
index b2c67617..1bae1894 100644
--- a/rsvg_internals/src/filters/flood.rs
+++ b/rsvg_internals/src/filters/flood.rs
@@ -28,7 +28,7 @@ impl NodeTrait for Flood {
impl_node_as_filter!();
#[inline]
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)
}
}
@@ -77,7 +77,7 @@ impl Filter for Flood {
}
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: SharedImageSurface::new(output_surface, SurfaceType::SRgb)?,
bounds,
diff --git a/rsvg_internals/src/filters/gaussian_blur.rs b/rsvg_internals/src/filters/gaussian_blur.rs
index 28bbd74f..723e643e 100644
--- a/rsvg_internals/src/filters/gaussian_blur.rs
+++ b/rsvg_internals/src/filters/gaussian_blur.rs
@@ -1,4 +1,3 @@
-use std::cell::Cell;
use std::cmp::min;
use std::f64;
@@ -28,7 +27,7 @@ const MAXIMUM_KERNEL_SIZE: usize = 500;
/// The `feGaussianBlur` filter primitive.
pub struct GaussianBlur {
base: PrimitiveWithInput,
- std_deviation: Cell<(f64, f64)>,
+ std_deviation: (f64, f64),
}
impl Default for GaussianBlur {
@@ -37,7 +36,7 @@ impl Default for GaussianBlur {
fn default() -> GaussianBlur {
GaussianBlur {
base: PrimitiveWithInput::new::<Self>(),
- std_deviation: Cell::new((0.0, 0.0)),
+ std_deviation: (0.0, 0.0),
}
}
}
@@ -45,13 +44,13 @@ impl Default for GaussianBlur {
impl NodeTrait for GaussianBlur {
impl_node_as_filter!();
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
- local_name!("stdDeviation") => self.std_deviation.set(
- parsers::number_optional_number(value)
+ local_name!("stdDeviation") => {
+ self.std_deviation = parsers::number_optional_number(value)
.attribute(attr.clone())
.and_then(|(x, y)| {
if x >= 0.0 && y >= 0.0 {
@@ -59,8 +58,8 @@ impl NodeTrait for GaussianBlur {
} else {
Err(NodeError::value_error(attr, "values can't be negative"))
}
- })?,
- ),
+ })?
+ }
_ => (),
}
}
@@ -212,7 +211,7 @@ impl Filter for GaussianBlur {
.add_input(&input)
.into_irect(draw_ctx);
- let (std_x, std_y) = self.std_deviation.get();
+ let (std_x, std_y) = self.std_deviation;
let (std_x, std_y) = ctx.paffine().transform_distance(std_x, std_y);
// The deviation can become negative here due to the transform.
@@ -248,7 +247,7 @@ impl Filter for GaussianBlur {
};
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: output_surface,
bounds,
diff --git a/rsvg_internals/src/filters/image.rs b/rsvg_internals/src/filters/image.rs
index 32c83a50..e5b06a71 100644
--- a/rsvg_internals/src/filters/image.rs
+++ b/rsvg_internals/src/filters/image.rs
@@ -1,5 +1,3 @@
-use std::cell::{Cell, RefCell};
-
use cairo::{self, ImageSurface, MatrixTrait, PatternTrait, Rectangle};
use markup5ever::local_name;
@@ -21,8 +19,8 @@ use super::{Filter, FilterError, Primitive};
/// The `feImage` filter primitive.
pub struct Image {
base: Primitive,
- aspect: Cell<AspectRatio>,
- href: RefCell<Option<Href>>,
+ aspect: AspectRatio,
+ href: Option<Href>,
}
impl Default for Image {
@@ -31,8 +29,8 @@ impl Default for Image {
fn default() -> Image {
Image {
base: Primitive::new::<Self>(),
- aspect: Cell::new(AspectRatio::default()),
- href: RefCell::new(None),
+ aspect: AspectRatio::default(),
+ href: None,
}
}
}
@@ -128,8 +126,7 @@ impl Image {
)?;
// TODO: this goes through a f64->i32->f64 conversion.
- let aspect = self.aspect.get();
- let (x, y, w, h) = aspect.compute(
+ let (x, y, w, h) = self.aspect.compute(
&ViewBox::new(
0.0,
0.0,
@@ -178,12 +175,12 @@ impl Image {
impl NodeTrait for Image {
impl_node_as_filter!();
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
- local_name!("preserveAspectRatio") => self.aspect.set(attr.parse(value)?),
+ local_name!("preserveAspectRatio") => self.aspect = attr.parse(value)?,
// "path" is used by some older Adobe Illustrator versions
local_name!("xlink:href") | local_name!("path") => {
@@ -191,7 +188,7 @@ impl NodeTrait for Image {
NodeError::parse_error(attr, ParseError::new("could not parse href"))
})?;
- *self.href.borrow_mut() = Some(href);
+ self.href = Some(href);
}
_ => (),
@@ -212,11 +209,8 @@ impl Filter for Image {
let bounds_builder = self.base.get_bounds(ctx);
let bounds = bounds_builder.into_irect(draw_ctx);
- let href_borrow = self.href.borrow();
- let href_opt = href_borrow.as_ref();
-
- if let Some(href) = href_opt {
- let output_surface = match *href {
+ if let Some(href) = self.href.as_ref() {
+ let output_surface = match href {
Href::PlainUrl(_) => {
let unclipped_bounds = bounds_builder.into_irect_without_clipping(draw_ctx);
self.render_external_image(ctx, draw_ctx, &bounds, &unclipped_bounds, href)?
@@ -225,7 +219,7 @@ impl Filter for Image {
};
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: SharedImageSurface::new(output_surface, SurfaceType::SRgb)?,
bounds,
diff --git a/rsvg_internals/src/filters/light/light_source.rs b/rsvg_internals/src/filters/light/light_source.rs
index 04a7175b..974a2d8f 100644
--- a/rsvg_internals/src/filters/light/light_source.rs
+++ b/rsvg_internals/src/filters/light/light_source.rs
@@ -1,5 +1,3 @@
-use std::cell::Cell;
-
use cairo::MatrixTrait;
use cssparser;
use markup5ever::local_name;
@@ -16,23 +14,23 @@ use crate::util::clamp;
#[derive(Clone)]
pub enum LightSource {
Distant {
- azimuth: Cell<f64>,
- elevation: Cell<f64>,
+ azimuth: f64,
+ elevation: f64,
},
Point {
- x: Cell<f64>,
- y: Cell<f64>,
- z: Cell<f64>,
+ x: f64,
+ y: f64,
+ z: f64,
},
Spot {
- x: Cell<f64>,
- y: Cell<f64>,
- z: Cell<f64>,
- points_at_x: Cell<f64>,
- points_at_y: Cell<f64>,
- points_at_z: Cell<f64>,
- specular_exponent: Cell<f64>,
- limiting_cone_angle: Cell<Option<f64>>,
+ x: f64,
+ y: f64,
+ z: f64,
+ points_at_x: f64,
+ points_at_y: f64,
+ points_at_z: f64,
+ specular_exponent: f64,
+ limiting_cone_angle: Option<f64>,
},
}
@@ -58,8 +56,8 @@ impl LightSource {
#[inline]
pub fn new_distant_light() -> LightSource {
LightSource::Distant {
- azimuth: Cell::new(0.0),
- elevation: Cell::new(0.0),
+ azimuth: 0.0,
+ elevation: 0.0,
}
}
@@ -67,9 +65,9 @@ impl LightSource {
#[inline]
pub fn new_point_light() -> LightSource {
LightSource::Point {
- x: Cell::new(0.0),
- y: Cell::new(0.0),
- z: Cell::new(0.0),
+ x: 0.0,
+ y: 0.0,
+ z: 0.0,
}
}
@@ -77,28 +75,27 @@ impl LightSource {
#[inline]
pub fn new_spot_light() -> LightSource {
LightSource::Spot {
- x: Cell::new(0.0),
- y: Cell::new(0.0),
- z: Cell::new(0.0),
- points_at_x: Cell::new(0.0),
- points_at_y: Cell::new(0.0),
- points_at_z: Cell::new(0.0),
- specular_exponent: Cell::new(0.0),
- limiting_cone_angle: Cell::new(None),
+ x: 0.0,
+ y: 0.0,
+ z: 0.0,
+ points_at_x: 0.0,
+ points_at_y: 0.0,
+ points_at_z: 0.0,
+ specular_exponent: 0.0,
+ limiting_cone_angle: None,
}
}
/// Returns a `TransformedLightSource` according to the given `FilterContext`.
#[inline]
pub fn transform(&self, ctx: &FilterContext) -> TransformedLightSource {
- match self {
- LightSource::Distant { azimuth, elevation } => TransformedLightSource::Distant {
- azimuth: azimuth.get(),
- elevation: elevation.get(),
- },
+ match *self {
+ LightSource::Distant { azimuth, elevation } => {
+ TransformedLightSource::Distant { azimuth, elevation }
+ }
LightSource::Point { x, y, z } => {
- let (x, y) = ctx.paffine().transform_point(x.get(), y.get());
- let z = ctx.transform_dist(z.get());
+ let (x, y) = ctx.paffine().transform_point(x, y);
+ let z = ctx.transform_dist(z);
TransformedLightSource::Point {
origin: Vector3::new(x, y, z),
@@ -114,12 +111,11 @@ impl LightSource {
specular_exponent,
limiting_cone_angle,
} => {
- let (x, y) = ctx.paffine().transform_point(x.get(), y.get());
- let z = ctx.transform_dist(z.get());
- let (points_at_x, points_at_y) = ctx
- .paffine()
- .transform_point(points_at_x.get(), points_at_y.get());
- let points_at_z = ctx.transform_dist(points_at_z.get());
+ let (x, y) = ctx.paffine().transform_point(x, y);
+ let z = ctx.transform_dist(z);
+ let (points_at_x, points_at_y) =
+ ctx.paffine().transform_point(points_at_x, points_at_y);
+ let points_at_z = ctx.transform_dist(points_at_z);
let origin = Vector3::new(x, y, z);
let mut direction = Vector3::new(points_at_x, points_at_y, points_at_z) - origin;
@@ -128,8 +124,8 @@ impl LightSource {
TransformedLightSource::Spot {
origin,
direction,
- specular_exponent: specular_exponent.get(),
- limiting_cone_angle: limiting_cone_angle.get(),
+ specular_exponent,
+ limiting_cone_angle,
}
}
}
@@ -200,56 +196,56 @@ impl TransformedLightSource {
}
impl NodeTrait for LightSource {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
- match self {
+ match *self {
LightSource::Distant {
- ref azimuth,
- ref elevation,
+ ref mut azimuth,
+ ref mut elevation,
} => match attr {
- local_name!("azimuth") => azimuth.set(parsers::number(value).attribute(attr)?),
+ local_name!("azimuth") => *azimuth = parsers::number(value).attribute(attr)?,
local_name!("elevation") => {
- elevation.set(parsers::number(value).attribute(attr)?)
+ *elevation = parsers::number(value).attribute(attr)?
}
_ => (),
},
LightSource::Point {
- ref x,
- ref y,
- ref z,
+ ref mut x,
+ ref mut y,
+ ref mut z,
} => match attr {
- local_name!("x") => x.set(parsers::number(value).attribute(attr)?),
- local_name!("y") => y.set(parsers::number(value).attribute(attr)?),
- local_name!("z") => z.set(parsers::number(value).attribute(attr)?),
+ local_name!("x") => *x = parsers::number(value).attribute(attr)?,
+ local_name!("y") => *y = parsers::number(value).attribute(attr)?,
+ local_name!("z") => *z = parsers::number(value).attribute(attr)?,
_ => (),
},
LightSource::Spot {
- ref x,
- ref y,
- ref z,
- ref points_at_x,
- ref points_at_y,
- ref points_at_z,
- ref specular_exponent,
- ref limiting_cone_angle,
+ ref mut x,
+ ref mut y,
+ ref mut z,
+ ref mut points_at_x,
+ ref mut points_at_y,
+ ref mut points_at_z,
+ ref mut specular_exponent,
+ ref mut limiting_cone_angle,
} => match attr {
- local_name!("x") => x.set(parsers::number(value).attribute(attr)?),
- local_name!("y") => y.set(parsers::number(value).attribute(attr)?),
- local_name!("z") => z.set(parsers::number(value).attribute(attr)?),
+ local_name!("x") => *x = parsers::number(value).attribute(attr)?,
+ local_name!("y") => *y = parsers::number(value).attribute(attr)?,
+ local_name!("z") => *z = parsers::number(value).attribute(attr)?,
local_name!("pointsAtX") => {
- points_at_x.set(parsers::number(value).attribute(attr)?)
+ *points_at_x = parsers::number(value).attribute(attr)?
}
local_name!("pointsAtY") => {
- points_at_y.set(parsers::number(value).attribute(attr)?)
+ *points_at_y = parsers::number(value).attribute(attr)?
}
local_name!("pointsAtZ") => {
- points_at_z.set(parsers::number(value).attribute(attr)?)
+ *points_at_z = parsers::number(value).attribute(attr)?
}
local_name!("specularExponent") => {
- specular_exponent.set(parsers::number(value).attribute(attr)?)
+ *specular_exponent = parsers::number(value).attribute(attr)?
}
local_name!("limitingConeAngle") => {
- limiting_cone_angle.set(Some(parsers::number(value).attribute(attr)?))
+ *limiting_cone_angle = Some(parsers::number(value).attribute(attr)?)
}
_ => (),
},
diff --git a/rsvg_internals/src/filters/light/lighting.rs b/rsvg_internals/src/filters/light/lighting.rs
index 5082e9e4..67e78fbe 100644
--- a/rsvg_internals/src/filters/light/lighting.rs
+++ b/rsvg_internals/src/filters/light/lighting.rs
@@ -1,4 +1,3 @@
-use std::cell::Cell;
use std::cmp::max;
use cairo::{self, ImageSurface, MatrixTrait};
@@ -41,19 +40,8 @@ use crate::surface_utils::{
use crate::util::clamp;
/// Properties specific to either diffuse or specular lighting.
-enum Data {
- Diffuse {
- diffuse_constant: Cell<f64>,
- },
- Specular {
- specular_constant: Cell<f64>,
- specular_exponent: Cell<f64>,
- },
-}
-
-/// `Data` but without `Cell`s, needed for sharing between threads.
#[derive(Clone, Copy)]
-enum RawData {
+enum Data {
Diffuse {
diffuse_constant: f64,
},
@@ -66,8 +54,8 @@ enum RawData {
/// The `feDiffuseLighting` and `feSpecularLighting` filter primitives.
pub struct Lighting {
base: PrimitiveWithInput,
- surface_scale: Cell<f64>,
- kernel_unit_length: Cell<Option<(f64, f64)>>,
+ surface_scale: f64,
+ kernel_unit_length: Option<(f64, f64)>,
data: Data,
}
@@ -77,7 +65,7 @@ impl Lighting {
pub fn new_diffuse() -> Lighting {
Lighting {
data: Data::Diffuse {
- diffuse_constant: Cell::new(1.0),
+ diffuse_constant: 1.0,
},
..Self::default()
}
@@ -88,8 +76,8 @@ impl Lighting {
pub fn new_specular() -> Lighting {
Lighting {
data: Data::Specular {
- specular_constant: Cell::new(1.0),
- specular_exponent: Cell::new(1.0),
+ specular_constant: 1.0,
+ specular_exponent: 1.0,
},
..Self::default()
}
@@ -99,40 +87,42 @@ impl Lighting {
impl NodeTrait for Lighting {
impl_node_as_filter!();
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
- local_name!("surfaceScale") => self.surface_scale.set(
- parsers::number(value).attribute(attr)?,
- ),
- 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!("surfaceScale") => {
+ self.surface_scale = parsers::number(value).attribute(attr)?
+ }
+ 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",
+ ))
+ }
+ })?,
+ )
+ }
_ => (),
}
}
match self.data {
Data::Diffuse {
- ref diffuse_constant,
+ ref mut diffuse_constant,
} => {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("diffuseConstant") => diffuse_constant.set(
- parsers::number(value)
+ local_name!("diffuseConstant") => {
+ *diffuse_constant = parsers::number(value)
.attribute(attr.clone())
.and_then(|x| {
if x >= 0.0 {
@@ -143,20 +133,20 @@ impl NodeTrait for Lighting {
"diffuseConstant can't be negative",
))
}
- })?,
- ),
+ })?;
+ }
_ => (),
}
}
}
Data::Specular {
- ref specular_constant,
- ref specular_exponent,
+ ref mut specular_constant,
+ ref mut specular_exponent,
} => {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("specularConstant") => specular_constant.set(
- parsers::number(value)
+ local_name!("specularConstant") => {
+ *specular_constant = parsers::number(value)
.attribute(attr.clone())
.and_then(|x| {
if x >= 0.0 {
@@ -167,10 +157,10 @@ impl NodeTrait for Lighting {
"specularConstant can't be negative",
))
}
- })?,
- ),
- local_name!("specularExponent") => specular_exponent.set(
- parsers::number(value)
+ })?;
+ }
+ local_name!("specularExponent") => {
+ *specular_exponent = parsers::number(value)
.attribute(attr.clone())
.and_then(|x| {
if x >= 1.0 && x <= 128.0 {
@@ -181,8 +171,8 @@ impl NodeTrait for Lighting {
"specularExponent should be between 1.0 and 128.0",
))
}
- })?,
- ),
+ })?;
+ }
_ => (),
}
}
@@ -210,11 +200,8 @@ impl Filter for Lighting {
let scale = self
.kernel_unit_length
- .get()
.map(|(dx, dy)| ctx.paffine().transform_distance(dx, dy));
- let surface_scale = self.surface_scale.get();
-
let cascaded = CascadedValues::new_from_node(node);
let values = cascaded.get();
let lighting_color = match values.lighting_color.0 {
@@ -271,7 +258,6 @@ impl Filter for Lighting {
{
let mut output_data = output_surface.get_data().unwrap();
let output_slice = &mut *output_data;
- let data = self.data.to_raw();
let compute_output_pixel =
|mut output_slice: &mut [u8], base_y, x, y, normal: Normal| {
@@ -279,18 +265,19 @@ impl Filter for Lighting {
let scaled_x = f64::from(x) * ox;
let scaled_y = f64::from(y) * oy;
- let z = f64::from(pixel.a) / 255.0 * surface_scale;
+ let z = f64::from(pixel.a) / 255.0 * self.surface_scale;
let light_vector = light_source.vector(scaled_x, scaled_y, z);
let light_color = light_source.color(lighting_color, light_vector);
- let factor = match data {
- RawData::Diffuse { diffuse_constant } => {
+ let factor = match self.data {
+ Data::Diffuse { diffuse_constant } => {
let k = if normal.normal.is_zero() {
// Common case of (0, 0, 1) normal.
light_vector.z
} else {
- let mut n =
- normal.normal.map(|x| f64::from(x) * surface_scale / 255.);
+ let mut n = normal
+ .normal
+ .map(|x| f64::from(x) * self.surface_scale / 255.);
n.component_mul_assign(&normal.factor);
let normal = Vector3::new(n.x, n.y, 1.0);
@@ -299,7 +286,7 @@ impl Filter for Lighting {
diffuse_constant * k
}
- RawData::Specular {
+ Data::Specular {
specular_constant,
specular_exponent,
} => {
@@ -317,8 +304,9 @@ impl Filter for Lighting {
n_dot_h.powf(specular_exponent)
}
} else {
- let mut n =
- normal.normal.map(|x| f64::from(x) * surface_scale / 255.);
+ let mut n = normal
+ .normal
+ .map(|x| f64::from(x) * self.surface_scale / 255.);
n.component_mul_assign(&normal.factor);
let normal = Vector3::new(n.x, n.y, 1.0);
@@ -344,7 +332,7 @@ impl Filter for Lighting {
a: 255,
};
- if let RawData::Specular { .. } = data {
+ if let Data::Specular { .. } = self.data {
output_pixel.a = max(max(output_pixel.r, output_pixel.g), output_pixel.b);
}
@@ -485,7 +473,7 @@ impl Filter for Lighting {
}
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: output_surface,
bounds,
@@ -499,35 +487,17 @@ impl Filter for Lighting {
}
}
-impl Data {
- #[inline]
- fn to_raw(&self) -> RawData {
- match self {
- Data::Diffuse { diffuse_constant } => RawData::Diffuse {
- diffuse_constant: diffuse_constant.get(),
- },
- Data::Specular {
- specular_constant,
- specular_exponent,
- } => RawData::Specular {
- specular_constant: specular_constant.get(),
- specular_exponent: specular_exponent.get(),
- },
- }
- }
-}
-
impl Default for Lighting {
#[inline]
fn default() -> Self {
Self {
base: PrimitiveWithInput::new::<Self>(),
- surface_scale: Cell::new(1.0),
- kernel_unit_length: Cell::new(None),
+ surface_scale: 1.0,
+ kernel_unit_length: None,
// The data field is unused in this case.
data: Data::Diffuse {
- diffuse_constant: Cell::new(1.0),
+ diffuse_constant: 1.0,
},
}
}
diff --git a/rsvg_internals/src/filters/merge.rs b/rsvg_internals/src/filters/merge.rs
index cd3e9051..bbb5e630 100644
--- a/rsvg_internals/src/filters/merge.rs
+++ b/rsvg_internals/src/filters/merge.rs
@@ -1,5 +1,3 @@
-use std::cell::RefCell;
-
use cairo::{self, ImageSurface};
use markup5ever::local_name;
@@ -21,7 +19,7 @@ pub struct Merge {
/// The `<feMergeNode>` element.
#[derive(Default)]
pub struct MergeNode {
- in_: RefCell<Option<Input>>,
+ in_: Option<Input>,
}
impl Default for Merge {
@@ -38,19 +36,17 @@ impl NodeTrait for Merge {
impl_node_as_filter!();
#[inline]
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)
}
}
impl NodeTrait for MergeNode {
#[inline]
- fn set_atts(&self, _parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("in") => {
- self.in_.replace(Some(Input::parse(attr, value)?));
- }
+ local_name!("in") => self.in_ = Some(Input::parse(attr, value)?),
_ => (),
}
}
@@ -67,7 +63,7 @@ impl MergeNode {
bounds: IRect,
output_surface: Option<SharedImageSurface>,
) -> Result<SharedImageSurface, FilterError> {
- let input = ctx.get_input(draw_ctx, self.in_.borrow().as_ref())?;
+ let input = ctx.get_input(draw_ctx, self.in_.as_ref())?;
if output_surface.is_none() {
return Ok(input.surface().clone());
@@ -131,7 +127,7 @@ impl Filter for Merge {
let input = ctx.get_input(
draw_ctx,
- child.borrow().get_impl::<MergeNode>().in_.borrow().as_ref(),
+ child.borrow().get_impl::<MergeNode>().in_.as_ref(),
)?;
bounds = bounds.add_input(&input);
}
@@ -164,7 +160,7 @@ impl Filter for Merge {
};
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: output_surface,
bounds,
diff --git a/rsvg_internals/src/filters/mod.rs b/rsvg_internals/src/filters/mod.rs
index 6cac6295..5f425676 100644
--- a/rsvg_internals/src/filters/mod.rs
+++ b/rsvg_internals/src/filters/mod.rs
@@ -1,4 +1,3 @@
-use std::cell::{Cell, RefCell};
use std::ops::Deref;
use std::time::Instant;
@@ -79,17 +78,17 @@ pub mod turbulence;
/// The base filter primitive node containing common properties.
struct Primitive {
- x: Cell<Option<LengthHorizontal>>,
- y: Cell<Option<LengthVertical>>,
- width: Cell<Option<LengthHorizontal>>,
- height: Cell<Option<LengthVertical>>,
- result: RefCell<Option<String>>,
+ x: Option<LengthHorizontal>,
+ y: Option<LengthVertical>,
+ width: Option<LengthHorizontal>,
+ height: Option<LengthVertical>,
+ result: Option<String>,
}
/// The base node for filter primitives which accept input.
struct PrimitiveWithInput {
base: Primitive,
- in_: RefCell<Option<Input>>,
+ in_: Option<Input>,
}
impl Primitive {
@@ -97,40 +96,28 @@ impl Primitive {
#[inline]
fn new<T: Filter>() -> Primitive {
Primitive {
- x: Cell::new(None),
- y: Cell::new(None),
- width: Cell::new(None),
- height: Cell::new(None),
- result: RefCell::new(None),
+ x: None,
+ y: None,
+ width: None,
+ height: None,
+ result: None,
}
}
/// Returns the `BoundsBuilder` for bounds computation.
#[inline]
fn get_bounds<'a>(&self, ctx: &'a FilterContext) -> BoundsBuilder<'a> {
- BoundsBuilder::new(
- ctx,
- self.x.get(),
- self.y.get(),
- self.width.get(),
- self.height.get(),
- )
+ BoundsBuilder::new(ctx, self.x, self.y, self.width, self.height)
}
}
impl NodeTrait for Primitive {
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
// With ObjectBoundingBox, only fractions and percents are allowed.
let primitiveunits = parent
.and_then(|parent| {
if parent.borrow().get_type() == NodeType::Filter {
- Some(
- parent
- .borrow()
- .get_impl::<NodeFilter>()
- .primitiveunits
- .get(),
- )
+ Some(parent.borrow().get_impl::<NodeFilter>().primitiveunits)
} else {
None
}
@@ -175,19 +162,27 @@ impl NodeTrait for Primitive {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("x") => self.x.set(Some(
- attr.parse_and_validate(value, check_units_horizontal)?,
- )),
- local_name!("y") => self
- .y
- .set(Some(attr.parse_and_validate(value, check_units_vertical)?)),
- local_name!("width") => self.width.set(Some(
- attr.parse_and_validate(value, check_units_horizontal_and_ensure_nonnegative)?,
- )),
- local_name!("height") => self.height.set(Some(
- attr.parse_and_validate(value, check_units_vertical_and_ensure_nonnegative)?,
- )),
- local_name!("result") => *self.result.borrow_mut() = Some(value.to_string()),
+ local_name!("x") => {
+ self.x = Some(attr.parse_and_validate(value, check_units_horizontal)?)
+ }
+ local_name!("y") => {
+ self.y = Some(attr.parse_and_validate(value, check_units_vertical)?)
+ }
+ local_name!("width") => {
+ self.width =
+ Some(attr.parse_and_validate(
+ value,
+ check_units_horizontal_and_ensure_nonnegative,
+ )?)
+ }
+ local_name!("height") => {
+ self.height =
+ Some(attr.parse_and_validate(
+ value,
+ check_units_vertical_and_ensure_nonnegative,
+ )?)
+ }
+ local_name!("result") => self.result = Some(value.to_string()),
_ => (),
}
}
@@ -202,7 +197,7 @@ impl PrimitiveWithInput {
fn new<T: Filter>() -> PrimitiveWithInput {
PrimitiveWithInput {
base: Primitive::new::<T>(),
- in_: RefCell::new(None),
+ in_: None,
}
}
@@ -213,17 +208,17 @@ impl PrimitiveWithInput {
ctx: &FilterContext,
draw_ctx: &mut DrawingCtx,
) -> Result<FilterInput, FilterError> {
- ctx.get_input(draw_ctx, self.in_.borrow().as_ref())
+ ctx.get_input(draw_ctx, self.in_.as_ref())
}
}
impl NodeTrait for PrimitiveWithInput {
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
- local_name!("in") => drop(self.in_.replace(Some(Input::parse(attr, value)?))),
+ local_name!("in") => drop(self.in_ = Some(Input::parse(attr, value)?)),
_ => (),
}
}
diff --git a/rsvg_internals/src/filters/morphology.rs b/rsvg_internals/src/filters/morphology.rs
index bd812437..23741166 100644
--- a/rsvg_internals/src/filters/morphology.rs
+++ b/rsvg_internals/src/filters/morphology.rs
@@ -1,4 +1,3 @@
-use std::cell::Cell;
use std::cmp::{max, min};
use cairo::{self, ImageSurface, MatrixTrait};
@@ -31,8 +30,8 @@ enum Operator {
/// The `feMorphology` filter primitive.
pub struct Morphology {
base: PrimitiveWithInput,
- operator: Cell<Operator>,
- radius: Cell<(f64, f64)>,
+ operator: Operator,
+ radius: (f64, f64),
}
impl Default for Morphology {
@@ -41,8 +40,8 @@ impl Default for Morphology {
fn default() -> Morphology {
Morphology {
base: PrimitiveWithInput::new::<Self>(),
- operator: Cell::new(Operator::Erode),
- radius: Cell::new((0.0, 0.0)),
+ operator: Operator::Erode,
+ radius: (0.0, 0.0),
}
}
}
@@ -50,14 +49,14 @@ impl Default for Morphology {
impl NodeTrait for Morphology {
impl_node_as_filter!();
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
- local_name!("operator") => self.operator.set(Operator::parse(attr, value)?),
- local_name!("radius") => self.radius.set(
- parsers::number_optional_number(value)
+ local_name!("operator") => self.operator = Operator::parse(attr, value)?,
+ local_name!("radius") => {
+ self.radius = parsers::number_optional_number(value)
.attribute(attr.clone())
.and_then(|(x, y)| {
if x >= 0.0 && y >= 0.0 {
@@ -65,8 +64,8 @@ impl NodeTrait for Morphology {
} else {
Err(NodeError::value_error(attr, "radius cannot be negative"))
}
- })?,
- ),
+ })?
+ }
_ => (),
}
}
@@ -89,15 +88,13 @@ impl Filter for Morphology {
.add_input(&input)
.into_irect(draw_ctx);
- let (rx, ry) = self.radius.get();
+ let (rx, ry) = self.radius;
let (rx, ry) = ctx.paffine().transform_distance(rx, ry);
// The radii can become negative here due to the transform.
let rx = rx.abs();
let ry = ry.abs();
- let operator = self.operator.get();
-
let mut output_surface = ImageSurface::create(
cairo::Format::ARgb32,
ctx.source_graphic().width(),
@@ -118,7 +115,7 @@ impl Filter for Morphology {
};
// Compute the new pixel values.
- let initial = match operator {
+ let initial = match self.operator {
Operator::Erode => u8::max_value(),
Operator::Dilate => u8::min_value(),
};
@@ -133,7 +130,7 @@ impl Filter for Morphology {
for (_x, _y, pixel) in
PixelRectangle::new(&input.surface(), bounds, kernel_bounds, EdgeMode::None)
{
- let op = match operator {
+ let op = match self.operator {
Operator::Erode => min,
Operator::Dilate => max,
};
@@ -149,7 +146,7 @@ impl Filter for Morphology {
}
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: SharedImageSurface::new(output_surface, input.surface().surface_type())?,
bounds,
diff --git a/rsvg_internals/src/filters/node.rs b/rsvg_internals/src/filters/node.rs
index 34be924b..1825aef0 100644
--- a/rsvg_internals/src/filters/node.rs
+++ b/rsvg_internals/src/filters/node.rs
@@ -1,6 +1,4 @@
//! The <filter> node.
-use std::cell::Cell;
-
use cairo::{self, MatrixTrait};
use markup5ever::local_name;
@@ -16,12 +14,12 @@ use crate::property_bag::PropertyBag;
/// The <filter> node.
pub struct NodeFilter {
- pub x: Cell<LengthHorizontal>,
- pub y: Cell<LengthVertical>,
- pub width: Cell<LengthHorizontal>,
- pub height: Cell<LengthVertical>,
- pub filterunits: Cell<CoordUnits>,
- pub primitiveunits: Cell<CoordUnits>,
+ pub x: LengthHorizontal,
+ pub y: LengthVertical,
+ pub width: LengthHorizontal,
+ pub height: LengthVertical,
+ pub filterunits: CoordUnits,
+ pub primitiveunits: CoordUnits,
}
impl Default for NodeFilter {
@@ -29,12 +27,12 @@ impl Default for NodeFilter {
#[inline]
fn default() -> Self {
Self {
- x: Cell::new(LengthHorizontal::parse_str("-10%").unwrap()),
- y: Cell::new(LengthVertical::parse_str("-10%").unwrap()),
- width: Cell::new(LengthHorizontal::parse_str("120%").unwrap()),
- height: Cell::new(LengthVertical::parse_str("120%").unwrap()),
- filterunits: Cell::new(CoordUnits::ObjectBoundingBox),
- primitiveunits: Cell::new(CoordUnits::UserSpaceOnUse),
+ x: LengthHorizontal::parse_str("-10%").unwrap(),
+ y: LengthVertical::parse_str("-10%").unwrap(),
+ width: LengthHorizontal::parse_str("120%").unwrap(),
+ height: LengthVertical::parse_str("120%").unwrap(),
+ filterunits: CoordUnits::ObjectBoundingBox,
+ primitiveunits: CoordUnits::UserSpaceOnUse,
}
}
}
@@ -63,7 +61,7 @@ impl NodeFilter {
// It's done this way because with ObjectBoundingBox, non-percentage values are supposed to
// represent the fractions of the referenced node, and with width and height = 1, 1 this
// works out exactly like that.
- let params = if self.filterunits.get() == CoordUnits::ObjectBoundingBox {
+ let params = if self.filterunits == CoordUnits::ObjectBoundingBox {
draw_ctx.push_view_box(1.0, 1.0)
} else {
draw_ctx.get_view_params()
@@ -71,19 +69,19 @@ impl NodeFilter {
// With filterunits == ObjectBoundingBox, lengths represent fractions or percentages of the
// referencing node. No units are allowed (it's checked during attribute parsing).
- let rect = if self.filterunits.get() == CoordUnits::ObjectBoundingBox {
+ let rect = if self.filterunits == CoordUnits::ObjectBoundingBox {
cairo::Rectangle {
- x: self.x.get().get_unitless(),
- y: self.y.get().get_unitless(),
- width: self.width.get().get_unitless(),
- height: self.height.get().get_unitless(),
+ x: self.x.get_unitless(),
+ y: self.y.get_unitless(),
+ width: self.width.get_unitless(),
+ height: self.height.get_unitless(),
}
} else {
cairo::Rectangle {
- x: self.x.get().normalize(values, &params),
- y: self.y.get().normalize(values, &params),
- width: self.width.get().normalize(values, &params),
- height: self.height.get().normalize(values, &params),
+ x: self.x.normalize(values, &params),
+ y: self.y.normalize(values, &params),
+ width: self.width.normalize(values, &params),
+ height: self.height.normalize(values, &params),
}
};
@@ -108,17 +106,17 @@ impl NodeFilter {
}
impl NodeTrait for NodeFilter {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
// Parse filterUnits first as it affects x, y, width, height checks.
for (attr, value) in pbag.iter() {
match attr {
- local_name!("filterUnits") => self.filterunits.set(attr.parse(value)?),
+ local_name!("filterUnits") => self.filterunits = attr.parse(value)?,
_ => (),
}
}
// With ObjectBoundingBox, only fractions and percents are allowed.
- let no_units_allowed = self.filterunits.get() == CoordUnits::ObjectBoundingBox;
+ let no_units_allowed = self.filterunits == CoordUnits::ObjectBoundingBox;
let check_units_horizontal = |length: LengthHorizontal| {
if !no_units_allowed {
@@ -157,19 +155,21 @@ impl NodeTrait for NodeFilter {
// Parse the rest of the attributes.
for (attr, value) in pbag.iter() {
match attr {
- local_name!("x") => self
- .x
- .set(attr.parse_and_validate(value, check_units_horizontal)?),
- local_name!("y") => self
- .y
- .set(attr.parse_and_validate(value, check_units_vertical)?),
- local_name!("width") => self.width.set(
- attr.parse_and_validate(value, check_units_horizontal_and_ensure_nonnegative)?,
- ),
- local_name!("height") => self.height.set(
- attr.parse_and_validate(value, check_units_vertical_and_ensure_nonnegative)?,
- ),
- local_name!("primitiveUnits") => self.primitiveunits.set(attr.parse(value)?),
+ local_name!("x") => {
+ self.x = attr.parse_and_validate(value, check_units_horizontal)?
+ }
+ local_name!("y") => {
+ self.y = attr.parse_and_validate(value, check_units_vertical)?
+ }
+ local_name!("width") => {
+ self.width = attr
+ .parse_and_validate(value, check_units_horizontal_and_ensure_nonnegative)?
+ }
+ local_name!("height") => {
+ self.height =
+ attr.parse_and_validate(value, check_units_vertical_and_ensure_nonnegative)?
+ }
+ local_name!("primitiveUnits") => self.primitiveunits = attr.parse(value)?,
_ => (),
}
}
diff --git a/rsvg_internals/src/filters/offset.rs b/rsvg_internals/src/filters/offset.rs
index 47ef0db5..e4fa299e 100644
--- a/rsvg_internals/src/filters/offset.rs
+++ b/rsvg_internals/src/filters/offset.rs
@@ -1,6 +1,5 @@
-use markup5ever::local_name;
use cairo::{self, ImageSurface, MatrixTrait};
-use std::cell::Cell;
+use markup5ever::local_name;
use crate::drawing_ctx::DrawingCtx;
use crate::error::AttributeResultExt;
@@ -17,8 +16,8 @@ use super::{Filter, FilterError, PrimitiveWithInput};
/// The `feOffset` filter primitive.
pub struct Offset {
base: PrimitiveWithInput,
- dx: Cell<f64>,
- dy: Cell<f64>,
+ dx: f64,
+ dy: f64,
}
impl Default for Offset {
@@ -27,8 +26,8 @@ impl Default for Offset {
fn default() -> Offset {
Offset {
base: PrimitiveWithInput::new::<Self>(),
- dx: Cell::new(0f64),
- dy: Cell::new(0f64),
+ dx: 0f64,
+ dy: 0f64,
}
}
}
@@ -36,17 +35,13 @@ impl Default for Offset {
impl NodeTrait for Offset {
impl_node_as_filter!();
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
- local_name!("dx") => self.dx.set(
- parsers::number(value).attribute(attr)?,
- ),
- local_name!("dy") => self.dy.set(
- parsers::number(value).attribute(attr)?,
- ),
+ local_name!("dx") => self.dx = parsers::number(value).attribute(attr)?,
+ local_name!("dy") => self.dy = parsers::number(value).attribute(attr)?,
_ => (),
}
}
@@ -69,9 +64,7 @@ impl Filter for Offset {
.add_input(&input)
.into_irect(draw_ctx);
- let dx = self.dx.get();
- let dy = self.dy.get();
- let (ox, oy) = ctx.paffine().transform_distance(dx, dy);
+ let (ox, oy) = ctx.paffine().transform_distance(self.dx, self.dy);
// output_bounds contains all pixels within bounds,
// for which (x - ox) and (y - oy) also lie within bounds.
@@ -103,7 +96,7 @@ impl Filter for Offset {
}
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: SharedImageSurface::new(output_surface, input.surface().surface_type())?,
bounds,
diff --git a/rsvg_internals/src/filters/tile.rs b/rsvg_internals/src/filters/tile.rs
index 821f8dfe..156a80f7 100644
--- a/rsvg_internals/src/filters/tile.rs
+++ b/rsvg_internals/src/filters/tile.rs
@@ -26,7 +26,7 @@ impl Default for Tile {
impl NodeTrait for Tile {
impl_node_as_filter!();
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)
}
}
@@ -98,7 +98,7 @@ impl Filter for Tile {
};
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: output_surface,
bounds,
diff --git a/rsvg_internals/src/filters/turbulence.rs b/rsvg_internals/src/filters/turbulence.rs
index 58db18f7..b096096b 100644
--- a/rsvg_internals/src/filters/turbulence.rs
+++ b/rsvg_internals/src/filters/turbulence.rs
@@ -1,5 +1,3 @@
-use std::cell::Cell;
-
use cairo::{self, ImageSurface, MatrixTrait};
use markup5ever::{local_name, LocalName};
@@ -36,11 +34,11 @@ enum NoiseType {
/// The `feTurbulence` filter primitive.
pub struct Turbulence {
base: Primitive,
- base_frequency: Cell<(f64, f64)>,
- num_octaves: Cell<i32>,
- seed: Cell<i32>,
- stitch_tiles: Cell<StitchTiles>,
- type_: Cell<NoiseType>,
+ base_frequency: (f64, f64),
+ num_octaves: i32,
+ seed: i32,
+ stitch_tiles: StitchTiles,
+ type_: NoiseType,
}
impl Default for Turbulence {
@@ -49,11 +47,11 @@ impl Default for Turbulence {
fn default() -> Turbulence {
Turbulence {
base: Primitive::new::<Self>(),
- base_frequency: Cell::new((0.0, 0.0)),
- num_octaves: Cell::new(1),
- seed: Cell::new(0),
- stitch_tiles: Cell::new(StitchTiles::NoStitch),
- type_: Cell::new(NoiseType::Turbulence),
+ base_frequency: (0.0, 0.0),
+ num_octaves: 1,
+ seed: 0,
+ stitch_tiles: StitchTiles::NoStitch,
+ type_: NoiseType::Turbulence,
}
}
}
@@ -62,13 +60,13 @@ impl NodeTrait for Turbulence {
impl_node_as_filter!();
#[inline]
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
- local_name!("baseFrequency") => self.base_frequency.set(
- parsers::number_optional_number(value)
+ local_name!("baseFrequency") => {
+ self.base_frequency = parsers::number_optional_number(value)
.attribute(attr.clone())
.and_then(|(x, y)| {
if x >= 0.0 && y >= 0.0 {
@@ -76,14 +74,14 @@ impl NodeTrait for Turbulence {
} else {
Err(NodeError::value_error(attr, "values can't be negative"))
}
- })?,
- ),
- local_name!("numOctaves") => self.num_octaves.set(
- parsers::integer(value).attribute(attr)?,
- ),
+ })?
+ }
+ local_name!("numOctaves") => {
+ self.num_octaves = parsers::integer(value).attribute(attr)?
+ }
// Yes, seed needs to be parsed as a number and then truncated.
- local_name!("seed") => self.seed.set(
- parsers::number(value)
+ local_name!("seed") => {
+ self.seed = parsers::number(value)
.map(|x| {
clamp(
x.trunc(),
@@ -91,12 +89,10 @@ impl NodeTrait for Turbulence {
f64::from(i32::max_value()),
) as i32
})
- .attribute(attr)?,
- ),
- local_name!("stitchTiles") => {
- self.stitch_tiles.set(StitchTiles::parse(attr, value)?)
+ .attribute(attr)?
}
- local_name!("type") => self.type_.set(NoiseType::parse(attr, value)?),
+ local_name!("stitchTiles") => self.stitch_tiles = StitchTiles::parse(attr, value)?,
+ local_name!("type") => self.type_ = NoiseType::parse(attr, value)?,
_ => (),
}
}
@@ -350,13 +346,12 @@ impl Filter for Turbulence {
let mut affine = ctx.paffine();
affine.invert();
- let type_ = self.type_.get();
let noise_generator = NoiseGenerator::new(
- self.seed.get(),
- self.base_frequency.get(),
- self.num_octaves.get(),
- type_,
- self.stitch_tiles.get(),
+ self.seed,
+ self.base_frequency,
+ self.num_octaves,
+ self.type_,
+ self.stitch_tiles,
f64::from(bounds.x1 - bounds.x0),
f64::from(bounds.y1 - bounds.y0),
);
@@ -384,7 +379,7 @@ impl Filter for Turbulence {
f64::from(y - bounds.y0),
);
- let v = match type_ {
+ let v = match self.type_ {
NoiseType::FractalNoise => (v * 255.0 + 255.0) / 2.0,
NoiseType::Turbulence => v * 255.0,
};
@@ -417,7 +412,7 @@ impl Filter for Turbulence {
};
Ok(FilterResult {
- name: self.base.result.borrow().clone(),
+ name: self.base.result.clone(),
output: FilterOutput {
surface: SharedImageSurface::new(output_surface, surface_type)?,
bounds,
diff --git a/rsvg_internals/src/gradient.rs b/rsvg_internals/src/gradient.rs
index 03a95384..087cba78 100644
--- a/rsvg_internals/src/gradient.rs
+++ b/rsvg_internals/src/gradient.rs
@@ -2,12 +2,10 @@ use cairo::{self, MatrixTrait};
use cssparser::{self, CowRcStr, Parser, Token};
use markup5ever::local_name;
-use std::cell::{Cell, RefCell};
-
use crate::allowed_url::Fragment;
use crate::bbox::*;
use crate::coord_units::CoordUnits;
-use crate::drawing_ctx::{AcquiredNode, DrawingCtx, NodeStack};
+use crate::drawing_ctx::{AcquiredNode, DrawingCtx, NodeStack, ViewParams};
use crate::error::*;
use crate::length::*;
use crate::node::{CascadedValues, NodeResult, NodeTrait, NodeType, RsvgNode};
@@ -82,7 +80,7 @@ macro_rules! fallback_to (
);
#[derive(Clone, Default)]
-pub struct GradientCommon {
+pub struct CommonGradientData {
pub units: Option<GradientUnits>,
pub affine: Option<cairo::Matrix>,
pub spread: Option<SpreadMethod>,
@@ -90,7 +88,7 @@ pub struct GradientCommon {
pub stops: Option<Vec<ColorStop>>,
}
-impl Resolve for GradientCommon {
+impl Resolve for CommonGradientData {
fn is_resolved(&self) -> bool {
self.units.is_some()
&& self.affine.is_some()
@@ -115,7 +113,23 @@ impl Resolve for GradientCommon {
}
}
-impl GradientCommon {
+impl CommonGradientData {
+ fn set_atts(&mut self, pbag: &PropertyBag<'_>) -> NodeResult {
+ for (attr, value) in pbag.iter() {
+ match attr {
+ local_name!("gradientUnits") => self.units = Some(attr.parse(value)?),
+ local_name!("gradientTransform") => self.affine = Some(attr.parse(value)?),
+ local_name!("spreadMethod") => self.spread = Some(attr.parse(value)?),
+ local_name!("xlink:href") => {
+ self.fallback = Some(Fragment::parse(value).attribute(attr)?)
+ }
+ _ => (),
+ }
+ }
+
+ Ok(())
+ }
+
fn clone_stops(&self) -> Option<Vec<ColorStop>> {
if let Some(ref stops) = self.stops {
Some(stops.clone())
@@ -244,14 +258,14 @@ impl GradientCommon {
}
#[derive(Copy, Clone, Default)]
-pub struct GradientLinear {
+pub struct LinearGradientData {
x1: Option<LengthHorizontal>,
y1: Option<LengthVertical>,
x2: Option<LengthHorizontal>,
y2: Option<LengthVertical>,
}
-impl Resolve for GradientLinear {
+impl Resolve for LinearGradientData {
fn is_resolved(&self) -> bool {
self.x1.is_some() && self.y1.is_some() && self.x2.is_some() && self.y2.is_some()
}
@@ -272,8 +286,37 @@ impl Resolve for GradientLinear {
}
}
+impl LinearGradientData {
+ fn set_atts(&mut self, pbag: &PropertyBag<'_>) -> NodeResult {
+ for (attr, value) in pbag.iter() {
+ match attr {
+ local_name!("x1") => self.x1 = Some(attr.parse(value)?),
+ local_name!("y1") => self.y1 = Some(attr.parse(value)?),
+ local_name!("x2") => self.x2 = Some(attr.parse(value)?),
+ local_name!("y2") => self.y2 = Some(attr.parse(value)?),
+ _ => (),
+ }
+ }
+
+ Ok(())
+ }
+
+ fn to_cairo_gradient(
+ &self,
+ values: &ComputedValues,
+ params: &ViewParams,
+ ) -> cairo::LinearGradient {
+ cairo::LinearGradient::new(
+ self.x1.as_ref().unwrap().normalize(values, params),
+ self.y1.as_ref().unwrap().normalize(values, params),
+ self.x2.as_ref().unwrap().normalize(values, params),
+ self.y2.as_ref().unwrap().normalize(values, params),
+ )
+ }
+}
+
#[derive(Copy, Clone, Default)]
-pub struct GradientRadial {
+pub struct RadialGradientData {
cx: Option<LengthHorizontal>,
cy: Option<LengthVertical>,
r: Option<LengthBoth>,
@@ -281,7 +324,7 @@ pub struct GradientRadial {
fy: Option<LengthVertical>,
}
-impl Resolve for GradientRadial {
+impl Resolve for RadialGradientData {
fn is_resolved(&self) -> bool {
self.cx.is_some()
&& self.cy.is_some()
@@ -310,6 +353,38 @@ impl Resolve for GradientRadial {
}
}
+impl RadialGradientData {
+ fn set_atts(&mut self, pbag: &PropertyBag<'_>) -> NodeResult {
+ for (attr, value) in pbag.iter() {
+ match attr {
+ local_name!("cx") => self.cx = Some(attr.parse(value)?),
+ local_name!("cy") => self.cy = Some(attr.parse(value)?),
+ local_name!("r") => self.r = Some(attr.parse(value)?),
+ local_name!("fx") => self.fx = Some(attr.parse(value)?),
+ local_name!("fy") => self.fy = Some(attr.parse(value)?),
+ _ => (),
+ }
+ }
+
+ Ok(())
+ }
+
+ fn to_cairo_gradient(
+ &self,
+ values: &ComputedValues,
+ params: &ViewParams,
+ ) -> cairo::RadialGradient {
+ let n_cx = self.cx.as_ref().unwrap().normalize(values, params);
+ let n_cy = self.cy.as_ref().unwrap().normalize(values, params);
+ let n_r = self.r.as_ref().unwrap().normalize(values, params);
+ let n_fx = self.fx.as_ref().unwrap().normalize(values, params);
+ let n_fy = self.fy.as_ref().unwrap().normalize(values, params);
+ let (new_fx, new_fy) = fix_focus_point(n_fx, n_fy, n_cx, n_cy, n_r);
+
+ cairo::RadialGradient::new(new_fx, new_fy, 0.0, n_cx, n_cy, n_r)
+ }
+}
+
// SVG defines radial gradients as being inside a circle (cx, cy, radius). The
// gradient projects out from a focus point (fx, fy), which is assumed to be
// inside the circle, to the edge of the circle.
@@ -351,12 +426,12 @@ fn fix_focus_point(fx: f64, fy: f64, cx: f64, cy: f64, radius: f64) -> (f64, f64
#[derive(Default)]
pub struct NodeStop {
- offset: Cell<UnitInterval>,
+ offset: UnitInterval,
}
impl NodeStop {
pub fn get_offset(&self) -> UnitInterval {
- self.offset.get()
+ self.offset
}
}
@@ -370,14 +445,13 @@ fn validate_offset(length: LengthBoth) -> Result<LengthBoth, ValueErrorKind> {
}
impl NodeTrait for NodeStop {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
local_name!("offset") => {
- self.offset.set(
- attr.parse_and_validate(value, validate_offset)
- .map(|l| UnitInterval::clamp(l.length()))?,
- );
+ self.offset = attr
+ .parse_and_validate(value, validate_offset)
+ .map(|l| UnitInterval::clamp(l.length()))?
}
_ => (),
}
@@ -387,88 +461,120 @@ impl NodeTrait for NodeStop {
}
}
+macro_rules! impl_node_trait {
+ ($gradient_type:ty) => {
+ impl NodeTrait for $gradient_type {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ self.common.set_atts(pbag)?;
+ self.variant.set_atts(pbag)?;
+ Ok(())
+ }
+ }
+ };
+}
+
macro_rules! impl_resolve {
($gradient_type:ty) => {
impl Resolve for $gradient_type {
fn is_resolved(&self) -> bool {
- self.common.borrow().is_resolved() && self.variant.borrow().is_resolved()
+ self.common.is_resolved() && self.variant.is_resolved()
}
fn resolve_from_fallback(&mut self, fallback: &$gradient_type) {
- self.common
- .borrow_mut()
- .resolve_from_fallback(&fallback.common.borrow());
- self.variant
- .borrow_mut()
- .resolve_from_fallback(&fallback.variant.borrow());
+ self.common.resolve_from_fallback(&fallback.common);
+ self.variant.resolve_from_fallback(&fallback.variant);
}
fn resolve_from_defaults(&mut self) {
- self.common.borrow_mut().resolve_from_defaults();
- self.variant.borrow_mut().resolve_from_defaults();
+ self.common.resolve_from_defaults();
+ self.variant.resolve_from_defaults();
}
}
};
}
-macro_rules! impl_paint_source_resolve {
- ($gradient:ty, $node_type:pat, $other_gradient:ty, $other_type:pat) => {
- fn resolve(
- &self,
- node: &RsvgNode,
- draw_ctx: &mut DrawingCtx,
- bbox: &BoundingBox,
- ) -> Result<Option<Self::Source>, RenderingError> {
- let mut result = self.clone();
- result.common.borrow_mut().add_color_stops_from_node(node);
+macro_rules! impl_paint_source {
+ ($gradient:ty, $node_type:pat, $other_gradient:ty, $other_type:pat, $cairo_pattern:expr) => {
+ impl PaintSource for $gradient {
+ type Source = $gradient;
- let mut stack = NodeStack::new();
+ fn resolve(
+ &self,
+ node: &RsvgNode,
+ draw_ctx: &mut DrawingCtx,
+ bbox: &BoundingBox,
+ ) -> Result<Option<Self::Source>, RenderingError> {
+ let mut result = self.clone();
+ result.common.add_color_stops_from_node(node);
- while !result.is_resolved() {
- let acquired = acquire_gradient(draw_ctx, result.common.borrow().fallback.as_ref());
+ let mut stack = NodeStack::new();
- if let Some(acquired) = acquired {
- let a_node = acquired.get();
+ while !result.is_resolved() {
+ let acquired = acquire_gradient(draw_ctx, result.common.fallback.as_ref());
- if stack.contains(a_node) {
- rsvg_log!("circular reference in gradient {}", node);
- return Err(RenderingError::CircularReference);
- }
+ if let Some(acquired) = acquired {
+ let a_node = acquired.get();
- match a_node.borrow().get_type() {
- // Same type, resolve all attributes
- $node_type => {
- let fallback = a_node
- .borrow()
- .get_impl::<$gradient>()
- .clone();
- fallback.common.borrow_mut().add_color_stops_from_node(a_node);
- result.resolve_from_fallback(&fallback);
+ if stack.contains(a_node) {
+ rsvg_log!("circular reference in gradient {}", node);
+ return Err(RenderingError::CircularReference);
}
- // Other type of gradient, resolve common attributes
- $other_type => {
- let fallback = a_node
- .borrow()
- .get_impl::<$other_gradient>()
- .clone();
- fallback.common.borrow_mut().add_color_stops_from_node(a_node);
- result.common.borrow_mut().resolve_from_fallback(&fallback.common.borrow());
+
+ match a_node.borrow().get_type() {
+ // Same type, resolve all attributes
+ $node_type => {
+ let mut fallback = a_node.borrow().get_impl::<$gradient>().clone();
+ fallback.common.add_color_stops_from_node(a_node);
+ result.resolve_from_fallback(&fallback);
+ }
+ // Other type of gradient, resolve common attributes
+ $other_type => {
+ let mut fallback =
+ a_node.borrow().get_impl::<$other_gradient>().clone();
+ fallback.common.add_color_stops_from_node(a_node);
+ result.common.resolve_from_fallback(&fallback.common);
+ }
+ _ => (),
}
- _ => (),
- }
- stack.push(a_node);
+ stack.push(a_node);
+
+ continue;
+ }
- continue;
+ result.resolve_from_defaults();
}
- result.resolve_from_defaults();
+ if result.common.bounds_are_valid(bbox) {
+ Ok(Some(result))
+ } else {
+ Ok(None)
+ }
}
- if result.common.borrow().bounds_are_valid(bbox) {
- Ok(Some(result))
- } else {
- Ok(None)
+ fn set_pattern_on_draw_context(
+ &self,
+ gradient: &Self::Source,
+ values: &ComputedValues,
+ draw_ctx: &mut DrawingCtx,
+ opacity: &UnitInterval,
+ bbox: &BoundingBox,
+ ) -> Result<bool, RenderingError> {
+ assert!(gradient.is_resolved());
+
+ let units = gradient.common.units.unwrap();
+ let params = if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
+ draw_ctx.push_view_box(1.0, 1.0)
+ } else {
+ draw_ctx.get_view_params()
+ };
+
+ let mut p = gradient.variant.to_cairo_gradient(values, &params);
+ gradient.common.set_on_pattern(&mut p, bbox, opacity);
+ let cr = draw_ctx.get_cairo_context();
+ cr.set_source(&$cairo_pattern(p));
+
+ Ok(true)
}
}
};
@@ -492,185 +598,39 @@ fn acquire_gradient<'a>(
#[derive(Clone, Default)]
pub struct NodeLinearGradient {
- pub common: RefCell<GradientCommon>,
- pub variant: RefCell<GradientLinear>,
+ pub common: CommonGradientData,
+ pub variant: LinearGradientData,
}
-impl NodeTrait for NodeLinearGradient {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
- let mut common = self.common.borrow_mut();
-
- let mut x1 = None;
- let mut y1 = None;
- let mut x2 = None;
- let mut y2 = None;
-
- for (attr, value) in pbag.iter() {
- match attr {
- // Attributes common to linear and radial gradients
- local_name!("gradientUnits") => common.units = Some(attr.parse(value)?),
- local_name!("gradientTransform") => common.affine = Some(attr.parse(value)?),
- local_name!("spreadMethod") => common.spread = Some(attr.parse(value)?),
- local_name!("xlink:href") => {
- common.fallback = Some(Fragment::parse(value).attribute(attr)?)
- }
-
- // Attributes specific to linear gradient
- local_name!("x1") => x1 = Some(attr.parse(value)?),
- local_name!("y1") => y1 = Some(attr.parse(value)?),
- local_name!("x2") => x2 = Some(attr.parse(value)?),
- local_name!("y2") => y2 = Some(attr.parse(value)?),
-
- _ => (),
- }
- }
-
- *self.variant.borrow_mut() = GradientLinear { x1, y1, x2, y2 };
-
- Ok(())
- }
-}
+impl_node_trait!(NodeLinearGradient);
impl_resolve!(NodeLinearGradient);
-impl PaintSource for NodeLinearGradient {
- type Source = NodeLinearGradient;
-
- impl_paint_source_resolve!(
- NodeLinearGradient,
- NodeType::LinearGradient,
- NodeRadialGradient,
- NodeType::RadialGradient
- );
-
- fn set_pattern_on_draw_context(
- &self,
- gradient: &Self::Source,
- values: &ComputedValues,
- draw_ctx: &mut DrawingCtx,
- opacity: &UnitInterval,
- bbox: &BoundingBox,
- ) -> Result<bool, RenderingError> {
- assert!(gradient.is_resolved());
-
- let units = gradient.common.borrow().units.unwrap();
- let params = if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
- draw_ctx.push_view_box(1.0, 1.0)
- } else {
- draw_ctx.get_view_params()
- };
-
- let v = gradient.variant.borrow();
- let mut pattern = cairo::LinearGradient::new(
- v.x1.as_ref().unwrap().normalize(values, &params),
- v.y1.as_ref().unwrap().normalize(values, &params),
- v.x2.as_ref().unwrap().normalize(values, &params),
- v.y2.as_ref().unwrap().normalize(values, &params),
- );
-
- let cr = draw_ctx.get_cairo_context();
- gradient
- .common
- .borrow_mut()
- .set_on_pattern(&mut pattern, bbox, opacity);
- cr.set_source(&cairo::Pattern::LinearGradient(pattern));
-
- Ok(true)
- }
-}
+impl_paint_source!(
+ NodeLinearGradient,
+ NodeType::LinearGradient,
+ NodeRadialGradient,
+ NodeType::RadialGradient,
+ cairo::Pattern::LinearGradient
+);
#[derive(Clone, Default)]
pub struct NodeRadialGradient {
- pub common: RefCell<GradientCommon>,
- pub variant: RefCell<GradientRadial>,
+ pub common: CommonGradientData,
+ pub variant: RadialGradientData,
}
-impl NodeTrait for NodeRadialGradient {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
- let mut common = self.common.borrow_mut();
-
- let mut cx = None;
- let mut cy = None;
- let mut r = None;
- let mut fx = None;
- let mut fy = None;
-
- for (attr, value) in pbag.iter() {
- match attr {
- // Attributes common to linear and radial gradients
- local_name!("gradientUnits") => common.units = Some(attr.parse(value)?),
- local_name!("gradientTransform") => common.affine = Some(attr.parse(value)?),
- local_name!("spreadMethod") => common.spread = Some(attr.parse(value)?),
- local_name!("xlink:href") => {
- common.fallback = Some(Fragment::parse(value).attribute(attr)?)
- }
-
- // Attributes specific to radial gradient
- local_name!("cx") => cx = Some(attr.parse(value)?),
- local_name!("cy") => cy = Some(attr.parse(value)?),
- local_name!("r") => r = Some(attr.parse(value)?),
- local_name!("fx") => fx = Some(attr.parse(value)?),
- local_name!("fy") => fy = Some(attr.parse(value)?),
-
- _ => (),
- }
- }
-
- *self.variant.borrow_mut() = GradientRadial { cx, cy, r, fx, fy };
-
- Ok(())
- }
-}
+impl_node_trait!(NodeRadialGradient);
impl_resolve!(NodeRadialGradient);
-impl PaintSource for NodeRadialGradient {
- type Source = NodeRadialGradient;
-
- impl_paint_source_resolve!(
- NodeRadialGradient,
- NodeType::RadialGradient,
- NodeLinearGradient,
- NodeType::LinearGradient
- );
-
- fn set_pattern_on_draw_context(
- &self,
- gradient: &Self::Source,
- values: &ComputedValues,
- draw_ctx: &mut DrawingCtx,
- opacity: &UnitInterval,
- bbox: &BoundingBox,
- ) -> Result<bool, RenderingError> {
- assert!(gradient.is_resolved());
-
- let units = gradient.common.borrow().units.unwrap();
- let params = if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
- draw_ctx.push_view_box(1.0, 1.0)
- } else {
- draw_ctx.get_view_params()
- };
-
- let v = gradient.variant.borrow();
- let n_cx = v.cx.as_ref().unwrap().normalize(values, &params);
- let n_cy = v.cy.as_ref().unwrap().normalize(values, &params);
- let n_r = v.r.as_ref().unwrap().normalize(values, &params);
- let n_fx = v.fx.as_ref().unwrap().normalize(values, &params);
- let n_fy = v.fy.as_ref().unwrap().normalize(values, &params);
-
- let (new_fx, new_fy) = fix_focus_point(n_fx, n_fy, n_cx, n_cy, n_r);
- let mut pattern = cairo::RadialGradient::new(new_fx, new_fy, 0.0, n_cx, n_cy, n_r);
-
- let cr = draw_ctx.get_cairo_context();
- gradient
- .common
- .borrow_mut()
- .set_on_pattern(&mut pattern, bbox, opacity);
- cr.set_source(&cairo::Pattern::RadialGradient(pattern));
-
- Ok(true)
- }
-}
+impl_paint_source!(
+ NodeRadialGradient,
+ NodeType::RadialGradient,
+ NodeLinearGradient,
+ NodeType::LinearGradient,
+ cairo::Pattern::RadialGradient
+);
#[cfg(test)]
mod tests {
diff --git a/rsvg_internals/src/image.rs b/rsvg_internals/src/image.rs
index 3a9af497..215ca355 100644
--- a/rsvg_internals/src/image.rs
+++ b/rsvg_internals/src/image.rs
@@ -1,7 +1,6 @@
use cairo;
use cairo::{PatternTrait, Rectangle};
use markup5ever::local_name;
-use std::cell::{Cell, RefCell};
use crate::allowed_url::Href;
use crate::aspect_ratio::AspectRatio;
@@ -18,28 +17,27 @@ use crate::viewbox::ViewBox;
#[derive(Default)]
pub struct NodeImage {
- aspect: Cell<AspectRatio>,
- x: Cell<LengthHorizontal>,
- y: Cell<LengthVertical>,
- w: Cell<LengthHorizontal>,
- h: Cell<LengthVertical>,
- href: RefCell<Option<Href>>,
+ x: LengthHorizontal,
+ y: LengthVertical,
+ w: LengthHorizontal,
+ h: LengthVertical,
+ aspect: AspectRatio,
+ href: Option<Href>,
}
impl NodeTrait for NodeImage {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("x") => self.x.set(attr.parse(value)?),
- local_name!("y") => self.y.set(attr.parse(value)?),
- local_name!("width") => self
- .w
- .set(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?),
- local_name!("height") => self
- .h
- .set(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?),
-
- local_name!("preserveAspectRatio") => self.aspect.set(attr.parse(value)?),
+ local_name!("x") => self.x = attr.parse(value)?,
+ local_name!("y") => self.y = attr.parse(value)?,
+ local_name!("width") => {
+ self.w = attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?
+ }
+ local_name!("height") => {
+ self.h = attr.parse_and_validate(value, LengthVertical::check_nonnegative)?
+ }
+ local_name!("preserveAspectRatio") => self.aspect = attr.parse(value)?,
// "path" is used by some older Adobe Illustrator versions
local_name!("xlink:href") | local_name!("path") => {
@@ -47,7 +45,7 @@ impl NodeTrait for NodeImage {
NodeError::parse_error(attr, ParseError::new("could not parse href"))
})?;
- *self.href.borrow_mut() = Some(href);
+ self.href = Some(href);
}
_ => (),
@@ -71,25 +69,23 @@ impl NodeTrait for NodeImage {
let values = cascaded.get();
let params = draw_ctx.get_view_params();
- let x = self.x.get().normalize(values, &params);
- let y = self.y.get().normalize(values, &params);
- let w = self.w.get().normalize(values, &params);
- let h = self.h.get().normalize(values, &params);
+ let x = self.x.normalize(values, &params);
+ let y = self.y.normalize(values, &params);
+ let w = self.w.normalize(values, &params);
+ let h = self.h.normalize(values, &params);
if w.approx_eq_cairo(&0.0) || h.approx_eq_cairo(&0.0) {
return Ok(());
}
draw_ctx.with_discrete_layer(node, values, clipping, &mut |dc| {
- let surface = if let Some(Href::PlainUrl(ref url)) = *self.href.borrow() {
+ let surface = if let Some(Href::PlainUrl(ref url)) = self.href {
dc.lookup_image(&url)?
} else {
return Ok(());
};
- let aspect = self.aspect.get();
-
- let clip_mode = if !values.is_overflow() && aspect.is_slice() {
+ let clip_mode = if !values.is_overflow() && self.aspect.is_slice() {
Some(ClipMode::ClipToViewport)
} else {
None
@@ -121,7 +117,7 @@ impl NodeTrait for NodeImage {
if let Some(_params) = dc.push_new_viewport(
Some(ViewBox::new(0.0, 0.0, image_width, image_height)),
&Rectangle::new(x, y, w, h),
- aspect,
+ self.aspect,
clip_mode,
) {
// We need to set extend appropriately, so can't use cr.set_source_surface().
diff --git a/rsvg_internals/src/link.rs b/rsvg_internals/src/link.rs
index 89ce6abe..cb0aeb11 100644
--- a/rsvg_internals/src/link.rs
+++ b/rsvg_internals/src/link.rs
@@ -2,7 +2,6 @@ use lazy_static::lazy_static;
use markup5ever::local_name;
use regex::{Captures, Regex};
use std::borrow::Cow;
-use std::cell::RefCell;
use crate::drawing_ctx::DrawingCtx;
use crate::error::RenderingError;
@@ -11,15 +10,14 @@ use crate::property_bag::PropertyBag;
#[derive(Default)]
pub struct NodeLink {
- link: RefCell<Option<String>>,
+ link: Option<String>,
}
impl NodeTrait for NodeLink {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("xlink:href") => *self.link.borrow_mut() = Some(value.to_owned()),
-
+ local_name!("xlink:href") => self.link = Some(value.to_owned()),
_ => (),
}
}
@@ -34,12 +32,10 @@ impl NodeTrait for NodeLink {
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<(), RenderingError> {
- let link = self.link.borrow();
-
let cascaded = CascadedValues::new(cascaded, node);
let values = cascaded.get();
- draw_ctx.with_discrete_layer(node, values, clipping, &mut |dc| match link.as_ref() {
+ draw_ctx.with_discrete_layer(node, values, clipping, &mut |dc| match self.link.as_ref() {
Some(l) if !l.is_empty() => {
const CAIRO_TAG_LINK: &str = "Link";
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index a44e9e84..fe39b9f6 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -1,10 +1,9 @@
-use std::cell::Cell;
use std::f64::consts::*;
use std::ops::Deref;
use cairo::Rectangle;
-use markup5ever::local_name;
use cssparser::{CowRcStr, Parser, Token};
+use markup5ever::local_name;
use crate::allowed_url::Fragment;
use crate::angle::Angle;
@@ -89,28 +88,28 @@ impl Parse for MarkerOrient {
}
pub struct NodeMarker {
- units: Cell<MarkerUnits>,
- ref_x: Cell<LengthHorizontal>,
- ref_y: Cell<LengthVertical>,
- width: Cell<LengthHorizontal>,
- height: Cell<LengthVertical>,
- orient: Cell<MarkerOrient>,
- aspect: Cell<AspectRatio>,
- vbox: Cell<Option<ViewBox>>,
+ units: MarkerUnits,
+ ref_x: LengthHorizontal,
+ ref_y: LengthVertical,
+ width: LengthHorizontal,
+ height: LengthVertical,
+ orient: MarkerOrient,
+ aspect: AspectRatio,
+ vbox: Option<ViewBox>,
}
impl Default for NodeMarker {
fn default() -> NodeMarker {
NodeMarker {
- units: Cell::new(MarkerUnits::default()),
- ref_x: Cell::new(Default::default()),
- ref_y: Cell::new(Default::default()),
+ units: MarkerUnits::default(),
+ ref_x: Default::default(),
+ ref_y: Default::default(),
// the following two are per the spec
- width: Cell::new(LengthHorizontal::parse_str("3").unwrap()),
- height: Cell::new(LengthVertical::parse_str("3").unwrap()),
- orient: Cell::new(MarkerOrient::default()),
- aspect: Cell::new(AspectRatio::default()),
- vbox: Cell::new(None),
+ width: LengthHorizontal::parse_str("3").unwrap(),
+ height: LengthVertical::parse_str("3").unwrap(),
+ orient: MarkerOrient::default(),
+ aspect: AspectRatio::default(),
+ vbox: None,
}
}
}
@@ -131,8 +130,8 @@ impl NodeMarker {
let params = draw_ctx.get_view_params();
- let marker_width = self.width.get().normalize(&values, &params);
- let marker_height = self.height.get().normalize(&values, &params);
+ let marker_width = self.width.normalize(&values, &params);
+ let marker_height = self.height.normalize(&values, &params);
if marker_width.approx_eq_cairo(&0.0) || marker_height.approx_eq_cairo(&0.0) {
// markerWidth or markerHeight set to 0 disables rendering of the element
@@ -145,19 +144,19 @@ impl NodeMarker {
cr.translate(xpos, ypos);
- let rotation = match self.orient.get() {
+ let rotation = match self.orient {
MarkerOrient::Auto => computed_angle,
MarkerOrient::Angle(a) => a,
};
cr.rotate(rotation.radians());
- if self.units.get() == MarkerUnits::StrokeWidth {
+ if self.units == MarkerUnits::StrokeWidth {
cr.scale(line_width, line_width);
}
- let params = if let Some(vbox) = self.vbox.get() {
- let (_, _, w, h) = self.aspect.get().compute(
+ let params = if let Some(vbox) = self.vbox {
+ let (_, _, w, h) = self.aspect.compute(
&vbox,
&Rectangle::new(0.0, 0.0, marker_width, marker_height),
);
@@ -174,12 +173,12 @@ impl NodeMarker {
};
cr.translate(
- -self.ref_x.get().normalize(&values, &params),
- -self.ref_y.get().normalize(&values, &params),
+ -self.ref_x.normalize(&values, &params),
+ -self.ref_y.normalize(&values, &params),
);
if !values.is_overflow() {
- if let Some(vbox) = self.vbox.get() {
+ if let Some(vbox) = self.vbox {
dc.clip(vbox.x, vbox.y, vbox.width, vbox.height);
} else {
dc.clip(0.0, 0.0, marker_width, marker_height);
@@ -194,29 +193,23 @@ impl NodeMarker {
}
impl NodeTrait for NodeMarker {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("markerUnits") => self.units.set(attr.parse(value)?),
-
- local_name!("refX") => self.ref_x.set(attr.parse(value)?),
-
- local_name!("refY") => self.ref_y.set(attr.parse(value)?),
-
- local_name!("markerWidth") => self
- .width
- .set(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?),
-
- local_name!("markerHeight") => self
- .height
- .set(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?),
-
- local_name!("orient") => self.orient.set(attr.parse(value)?),
-
- local_name!("preserveAspectRatio") => self.aspect.set(attr.parse(value)?),
-
- local_name!("viewBox") => self.vbox.set(Some(attr.parse(value)?)),
-
+ local_name!("markerUnits") => self.units = attr.parse(value)?,
+ local_name!("refX") => self.ref_x = attr.parse(value)?,
+ local_name!("refY") => self.ref_y = attr.parse(value)?,
+ local_name!("markerWidth") => {
+ self.width =
+ attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?
+ }
+ local_name!("markerHeight") => {
+ self.height =
+ attr.parse_and_validate(value, LengthVertical::check_nonnegative)?
+ }
+ local_name!("orient") => self.orient = attr.parse(value)?,
+ local_name!("preserveAspectRatio") => self.aspect = attr.parse(value)?,
+ local_name!("viewBox") => self.vbox = Some(attr.parse(value)?),
_ => (),
}
}
diff --git a/rsvg_internals/src/mask.rs b/rsvg_internals/src/mask.rs
index 9d990a18..e5a50947 100644
--- a/rsvg_internals/src/mask.rs
+++ b/rsvg_internals/src/mask.rs
@@ -1,6 +1,5 @@
use cairo::{self, MatrixTrait};
use markup5ever::local_name;
-use std::cell::Cell;
use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
@@ -24,27 +23,26 @@ coord_units!(MaskUnits, CoordUnits::ObjectBoundingBox);
coord_units!(MaskContentUnits, CoordUnits::UserSpaceOnUse);
pub struct NodeMask {
- x: Cell<LengthHorizontal>,
- y: Cell<LengthVertical>,
- width: Cell<LengthHorizontal>,
- height: Cell<LengthVertical>,
+ x: LengthHorizontal,
+ y: LengthVertical,
+ width: LengthHorizontal,
+ height: LengthVertical,
- units: Cell<MaskUnits>,
- content_units: Cell<MaskContentUnits>,
+ units: MaskUnits,
+ content_units: MaskContentUnits,
}
impl Default for NodeMask {
fn default() -> NodeMask {
NodeMask {
// these values are per the spec
- x: Cell::new(LengthHorizontal::parse_str("-10%").unwrap()),
- y: Cell::new(LengthVertical::parse_str("-10%").unwrap()),
+ x: LengthHorizontal::parse_str("-10%").unwrap(),
+ y: LengthVertical::parse_str("-10%").unwrap(),
+ width: LengthHorizontal::parse_str("120%").unwrap(),
+ height: LengthVertical::parse_str("120%").unwrap(),
- width: Cell::new(LengthHorizontal::parse_str("120%").unwrap()),
- height: Cell::new(LengthVertical::parse_str("120%").unwrap()),
-
- units: Cell::new(MaskUnits::default()),
- content_units: Cell::new(MaskContentUnits::default()),
+ units: MaskUnits::default(),
+ content_units: MaskContentUnits::default(),
}
}
}
@@ -70,8 +68,8 @@ impl NodeMask {
let mask_content_surface = draw_ctx.create_surface_for_toplevel_viewport()?;
- let mask_units = CoordUnits::from(self.units.get());
- let content_units = CoordUnits::from(self.content_units.get());
+ let mask_units = CoordUnits::from(self.units);
+ let content_units = CoordUnits::from(self.content_units);
let (x, y, w, h) = {
let params = if mask_units == CoordUnits::ObjectBoundingBox {
@@ -80,10 +78,10 @@ impl NodeMask {
draw_ctx.get_view_params()
};
- let x = self.x.get().normalize(&values, &params);
- let y = self.y.get().normalize(&values, &params);
- let w = self.width.get().normalize(&values, &params);
- let h = self.height.get().normalize(&values, &params);
+ let x = self.x.normalize(&values, &params);
+ let y = self.y.normalize(&values, &params);
+ let w = self.width.normalize(&values, &params);
+ let h = self.height.normalize(&values, &params);
(x, y, w, h)
};
@@ -188,19 +186,21 @@ fn compute_luminance_to_alpha(
}
impl NodeTrait for NodeMask {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("x") => self.x.set(attr.parse(value)?),
- local_name!("y") => self.y.set(attr.parse(value)?),
- local_name!("width") => self
- .width
- .set(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?),
- local_name!("height") => self
- .height
- .set(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?),
- local_name!("maskUnits") => self.units.set(attr.parse(value)?),
- local_name!("maskContentUnits") => self.content_units.set(attr.parse(value)?),
+ local_name!("x") => self.x = attr.parse(value)?,
+ local_name!("y") => self.y = attr.parse(value)?,
+ local_name!("width") => {
+ self.width =
+ attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?
+ }
+ local_name!("height") => {
+ self.height =
+ attr.parse_and_validate(value, LengthVertical::check_nonnegative)?
+ }
+ local_name!("maskUnits") => self.units = attr.parse(value)?,
+ local_name!("maskContentUnits") => self.content_units = attr.parse(value)?,
_ => (),
}
}
diff --git a/rsvg_internals/src/node.rs b/rsvg_internals/src/node.rs
index 2937b9b1..30a64236 100644
--- a/rsvg_internals/src/node.rs
+++ b/rsvg_internals/src/node.rs
@@ -341,7 +341,7 @@ pub trait NodeTrait: Downcast {
/// Sets per-node attributes from the `pbag`
///
/// Each node is supposed to iterate the `pbag`, and parse any attributes it needs.
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult;
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult;
/// Sets any special-cased properties that the node may have, that are different
/// from defaults in the node's `SpecifiedValues`.
diff --git a/rsvg_internals/src/pattern.rs b/rsvg_internals/src/pattern.rs
index 5859da91..42606b30 100644
--- a/rsvg_internals/src/pattern.rs
+++ b/rsvg_internals/src/pattern.rs
@@ -25,7 +25,7 @@ coord_units!(PatternUnits, CoordUnits::ObjectBoundingBox);
coord_units!(PatternContentUnits, CoordUnits::UserSpaceOnUse);
#[derive(Clone, Default)]
-pub struct Pattern {
+pub struct PatternData {
pub units: Option<PatternUnits>,
pub content_units: Option<PatternContentUnits>,
// This Option<Option<ViewBox>> is a bit strange. We want a field
@@ -44,7 +44,7 @@ pub struct Pattern {
// Point back to our corresponding node, or to the fallback node which has children.
// If the value is None, it means we are fully resolved and didn't find any children
// among the fallbacks.
- pub node: Option<RsvgWeakNode>,
+ pub node: RefCell<Option<RsvgWeakNode>>,
}
macro_rules! fallback_to (
@@ -53,7 +53,7 @@ macro_rules! fallback_to (
);
);
-impl Resolve for Pattern {
+impl Resolve for PatternData {
fn is_resolved(&self) -> bool {
self.units.is_some()
&& self.content_units.is_some()
@@ -67,7 +67,7 @@ impl Resolve for Pattern {
&& self.children_are_resolved()
}
- fn resolve_from_fallback(&mut self, fallback: &Pattern) {
+ fn resolve_from_fallback(&mut self, fallback: &PatternData) {
fallback_to!(self.units, fallback.units);
fallback_to!(self.content_units, fallback.content_units);
fallback_to!(self.vbox, fallback.vbox);
@@ -81,10 +81,10 @@ impl Resolve for Pattern {
self.fallback = fallback.fallback.clone();
if !self.children_are_resolved() {
- if fallback.node.is_some() {
- self.node = fallback.node.clone();
+ if fallback.node.borrow().is_some() {
+ *self.node.borrow_mut() = fallback.node.borrow().clone();
} else {
- self.node = None;
+ *self.node.borrow_mut() = None;
}
}
}
@@ -102,9 +102,9 @@ impl Resolve for Pattern {
}
}
-impl Pattern {
+impl PatternData {
fn children_are_resolved(&self) -> bool {
- if let Some(ref weak) = self.node {
+ if let Some(ref weak) = *self.node.borrow() {
let strong_node = &weak.clone().upgrade().unwrap();
strong_node.has_children()
} else {
@@ -116,53 +116,43 @@ impl Pattern {
}
pub struct NodePattern {
- pattern: RefCell<Pattern>,
+ pattern: PatternData,
}
impl Default for NodePattern {
fn default() -> NodePattern {
NodePattern {
- pattern: RefCell::new(Pattern::default()),
+ pattern: PatternData::default(),
}
}
}
impl NodeTrait for NodePattern {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
- let mut p = self.pattern.borrow_mut();
-
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("patternUnits") => p.units = Some(attr.parse(value)?),
-
- local_name!("patternContentUnits") => p.content_units = Some(attr.parse(value)?),
-
- local_name!("viewBox") => p.vbox = Some(Some(attr.parse(value)?)),
-
+ local_name!("patternUnits") => self.pattern.units = Some(attr.parse(value)?),
+ local_name!("patternContentUnits") => {
+ self.pattern.content_units = Some(attr.parse(value)?)
+ }
+ local_name!("viewBox") => self.pattern.vbox = Some(Some(attr.parse(value)?)),
local_name!("preserveAspectRatio") => {
- p.preserve_aspect_ratio = Some(attr.parse(value)?)
+ self.pattern.preserve_aspect_ratio = Some(attr.parse(value)?)
}
-
- local_name!("patternTransform") => p.affine = Some(attr.parse(value)?),
-
+ local_name!("patternTransform") => self.pattern.affine = Some(attr.parse(value)?),
local_name!("xlink:href") => {
- p.fallback = Some(Fragment::parse(value).attribute(attr)?);
+ self.pattern.fallback = Some(Fragment::parse(value).attribute(attr)?);
}
-
- local_name!("x") => p.x = Some(attr.parse(value)?),
-
- local_name!("y") => p.y = Some(attr.parse(value)?),
-
+ local_name!("x") => self.pattern.x = Some(attr.parse(value)?),
+ local_name!("y") => self.pattern.y = Some(attr.parse(value)?),
local_name!("width") => {
- p.width =
+ self.pattern.width =
Some(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?)
}
-
local_name!("height") => {
- p.height =
+ self.pattern.height =
Some(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?)
}
-
_ => (),
}
}
@@ -176,7 +166,7 @@ impl NodeTrait for NodePattern {
}
impl PaintSource for NodePattern {
- type Source = Pattern;
+ type Source = PatternData;
fn resolve(
&self,
@@ -184,18 +174,9 @@ impl PaintSource for NodePattern {
draw_ctx: &mut DrawingCtx,
_bbox: &BoundingBox,
) -> Result<Option<Self::Source>, RenderingError> {
- {
- // Initialize pattern.node and release the mutable borrow
- let mut p = self.pattern.borrow_mut();
- p.node = Some(node.downgrade());
- }
+ *self.pattern.node.borrow_mut() = Some(node.downgrade());
- let mut result = node
- .borrow()
- .get_impl::<NodePattern>()
- .pattern
- .borrow()
- .clone();
+ let mut result = node.borrow().get_impl::<NodePattern>().pattern.clone();
let mut stack = NodeStack::new();
while !result.is_resolved() {
@@ -211,8 +192,7 @@ impl PaintSource for NodePattern {
}
let node_data = a_node.borrow();
- let fallback = node_data.get_impl::<NodePattern>().pattern.borrow();
- result.resolve_from_fallback(&fallback);
+ result.resolve_from_fallback(&node_data.get_impl::<NodePattern>().pattern);
stack.push(a_node);
} else {
@@ -233,7 +213,7 @@ impl PaintSource for NodePattern {
) -> Result<bool, RenderingError> {
assert!(pattern.is_resolved());
- if pattern.node.is_none() {
+ if pattern.node.borrow().is_none() {
// This means we didn't find any children among the fallbacks,
// so there is nothing to render.
return Ok(false);
@@ -382,7 +362,7 @@ impl PaintSource for NodePattern {
// Set up transformations to be determined by the contents units
// Draw everything
- let pattern_node = pattern.node.as_ref().unwrap().upgrade().unwrap();
+ let pattern_node = pattern.node.borrow().as_ref().unwrap().upgrade().unwrap();
let pattern_cascaded = CascadedValues::new_from_node(&pattern_node);
let pattern_values = pattern_cascaded.get();
@@ -419,7 +399,7 @@ mod tests {
#[test]
fn pattern_resolved_from_defaults_is_really_resolved() {
- let mut pat = Pattern::default();
+ let mut pat = PatternData::default();
pat.resolve_from_defaults();
assert!(pat.is_resolved());
diff --git a/rsvg_internals/src/shapes.rs b/rsvg_internals/src/shapes.rs
index aacc9bfb..5d03fb00 100644
--- a/rsvg_internals/src/shapes.rs
+++ b/rsvg_internals/src/shapes.rs
@@ -1,7 +1,5 @@
use cairo;
use markup5ever::local_name;
-use std::cell::Cell;
-use std::cell::RefCell;
use std::ops::Deref;
use crate::drawing_ctx::DrawingCtx;
@@ -112,11 +110,11 @@ fn render_ellipse(
#[derive(Default)]
pub struct NodePath {
- builder: RefCell<Option<PathBuilder>>,
+ builder: Option<PathBuilder>,
}
impl NodeTrait for NodePath {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
if attr == local_name!("d") {
let mut builder = PathBuilder::new();
@@ -128,7 +126,7 @@ impl NodeTrait for NodePath {
rsvg_log!("could not parse path: {}", e);
}
- *self.builder.borrow_mut() = Some(builder);
+ self.builder = Some(builder);
}
}
@@ -144,7 +142,7 @@ impl NodeTrait for NodePath {
) -> Result<(), RenderingError> {
let values = cascaded.get();
- if let Some(ref builder) = *self.builder.borrow() {
+ if let Some(ref builder) = self.builder {
render_path_builder(builder, draw_ctx, node, values, true, clipping)?;
}
@@ -199,31 +197,31 @@ impl Parse for Points {
}
pub struct NodePoly {
- points: RefCell<Option<Points>>,
+ points: Option<Points>,
kind: PolyKind,
}
impl NodePoly {
pub fn new_open() -> NodePoly {
NodePoly {
- points: RefCell::new(None),
+ points: None,
kind: PolyKind::Open,
}
}
pub fn new_closed() -> NodePoly {
NodePoly {
- points: RefCell::new(None),
+ points: None,
kind: PolyKind::Closed,
}
}
}
impl NodeTrait for NodePoly {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
if attr == local_name!("points") {
- *self.points.borrow_mut() = attr.parse(value.trim()).map(Some)?;
+ self.points = attr.parse(value.trim()).map(Some)?;
}
}
@@ -239,7 +237,7 @@ impl NodeTrait for NodePoly {
) -> Result<(), RenderingError> {
let values = cascaded.get();
- if let Some(ref points) = *self.points.borrow() {
+ if let Some(ref points) = self.points {
let mut builder = PathBuilder::new();
for (i, &(x, y)) in points.iter().enumerate() {
@@ -263,20 +261,20 @@ impl NodeTrait for NodePoly {
#[derive(Default)]
pub struct NodeLine {
- x1: Cell<LengthHorizontal>,
- y1: Cell<LengthVertical>,
- x2: Cell<LengthHorizontal>,
- y2: Cell<LengthVertical>,
+ x1: LengthHorizontal,
+ y1: LengthVertical,
+ x2: LengthHorizontal,
+ y2: LengthVertical,
}
impl NodeTrait for NodeLine {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("x1") => self.x1.set(attr.parse(value)?),
- local_name!("y1") => self.y1.set(attr.parse(value)?),
- local_name!("x2") => self.x2.set(attr.parse(value)?),
- local_name!("y2") => self.y2.set(attr.parse(value)?),
+ local_name!("x1") => self.x1 = attr.parse(value)?,
+ local_name!("y1") => self.y1 = attr.parse(value)?,
+ local_name!("x2") => self.x2 = attr.parse(value)?,
+ local_name!("y2") => self.y2 = attr.parse(value)?,
_ => (),
}
}
@@ -297,10 +295,10 @@ impl NodeTrait for NodeLine {
let params = draw_ctx.get_view_params();
- let x1 = self.x1.get().normalize(values, &params);
- let y1 = self.y1.get().normalize(values, &params);
- let x2 = self.x2.get().normalize(values, &params);
- let y2 = self.y2.get().normalize(values, &params);
+ let x1 = self.x1.normalize(values, &params);
+ let y1 = self.y1.normalize(values, &params);
+ let x2 = self.x2.normalize(values, &params);
+ let y2 = self.y2.normalize(values, &params);
builder.move_to(x1, y1);
builder.line_to(x2, y2);
@@ -311,38 +309,38 @@ impl NodeTrait for NodeLine {
#[derive(Default)]
pub struct NodeRect {
- // x, y, width, height
- x: Cell<LengthHorizontal>,
- y: Cell<LengthVertical>,
- w: Cell<LengthHorizontal>,
- h: Cell<LengthVertical>,
+ x: LengthHorizontal,
+ y: LengthVertical,
+ w: LengthHorizontal,
+ h: LengthVertical,
// Radiuses for rounded corners
- rx: Cell<Option<LengthHorizontal>>,
- ry: Cell<Option<LengthVertical>>,
+ rx: Option<LengthHorizontal>,
+ ry: Option<LengthVertical>,
}
impl NodeTrait for NodeRect {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("x") => self.x.set(attr.parse(value)?),
- local_name!("y") => self.y.set(attr.parse(value)?),
- local_name!("width") => self
- .w
- .set(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?),
- local_name!("height") => self
- .h
- .set(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?),
- local_name!("rx") => self.rx.set(
- attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)
- .map(Some)?,
- ),
- local_name!("ry") => self.ry.set(
- attr.parse_and_validate(value, LengthVertical::check_nonnegative)
- .map(Some)?,
- ),
-
+ local_name!("x") => self.x = attr.parse(value)?,
+ local_name!("y") => self.y = attr.parse(value)?,
+ local_name!("width") => {
+ self.w = attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?
+ }
+ local_name!("height") => {
+ self.h = attr.parse_and_validate(value, LengthVertical::check_nonnegative)?
+ }
+ local_name!("rx") => {
+ self.rx = attr
+ .parse_and_validate(value, LengthHorizontal::check_nonnegative)
+ .map(Some)?
+ }
+ local_name!("ry") => {
+ self.ry = attr
+ .parse_and_validate(value, LengthVertical::check_nonnegative)
+ .map(Some)?
+ }
_ => (),
}
}
@@ -361,15 +359,15 @@ impl NodeTrait for NodeRect {
let params = draw_ctx.get_view_params();
- let x = self.x.get().normalize(values, &params);
- let y = self.y.get().normalize(values, &params);
- let w = self.w.get().normalize(values, &params);
- let h = self.h.get().normalize(values, &params);
+ let x = self.x.normalize(values, &params);
+ let y = self.y.normalize(values, &params);
+ let w = self.w.normalize(values, &params);
+ let h = self.h.normalize(values, &params);
let mut rx;
let mut ry;
- match (self.rx.get(), self.ry.get()) {
+ match (self.rx, self.ry) {
(None, None) => {
rx = 0.0;
ry = 0.0;
@@ -532,21 +530,20 @@ impl NodeTrait for NodeRect {
#[derive(Default)]
pub struct NodeCircle {
- cx: Cell<LengthHorizontal>,
- cy: Cell<LengthVertical>,
- r: Cell<LengthBoth>,
+ cx: LengthHorizontal,
+ cy: LengthVertical,
+ r: LengthBoth,
}
impl NodeTrait for NodeCircle {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("cx") => self.cx.set(attr.parse(value)?),
- local_name!("cy") => self.cy.set(attr.parse(value)?),
- local_name!("r") => self
- .r
- .set(attr.parse_and_validate(value, LengthBoth::check_nonnegative)?),
-
+ local_name!("cx") => self.cx = attr.parse(value)?,
+ local_name!("cy") => self.cy = attr.parse(value)?,
+ local_name!("r") => {
+ self.r = attr.parse_and_validate(value, LengthBoth::check_nonnegative)?
+ }
_ => (),
}
}
@@ -565,9 +562,9 @@ impl NodeTrait for NodeCircle {
let params = draw_ctx.get_view_params();
- let cx = self.cx.get().normalize(values, &params);
- let cy = self.cy.get().normalize(values, &params);
- let r = self.r.get().normalize(values, &params);
+ let cx = self.cx.normalize(values, &params);
+ let cy = self.cy.normalize(values, &params);
+ let r = self.r.normalize(values, &params);
render_ellipse(cx, cy, r, r, draw_ctx, node, values, clipping)
}
@@ -575,25 +572,24 @@ impl NodeTrait for NodeCircle {
#[derive(Default)]
pub struct NodeEllipse {
- cx: Cell<LengthHorizontal>,
- cy: Cell<LengthVertical>,
- rx: Cell<LengthHorizontal>,
- ry: Cell<LengthVertical>,
+ cx: LengthHorizontal,
+ cy: LengthVertical,
+ rx: LengthHorizontal,
+ ry: LengthVertical,
}
impl NodeTrait for NodeEllipse {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("cx") => self.cx.set(attr.parse(value)?),
- local_name!("cy") => self.cy.set(attr.parse(value)?),
- local_name!("rx") => self
- .rx
- .set(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?),
- local_name!("ry") => self
- .ry
- .set(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?),
-
+ local_name!("cx") => self.cx = attr.parse(value)?,
+ local_name!("cy") => self.cy = attr.parse(value)?,
+ local_name!("rx") => {
+ self.rx = attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?
+ }
+ local_name!("ry") => {
+ self.ry = attr.parse_and_validate(value, LengthVertical::check_nonnegative)?
+ }
_ => (),
}
}
@@ -612,10 +608,10 @@ impl NodeTrait for NodeEllipse {
let params = draw_ctx.get_view_params();
- let cx = self.cx.get().normalize(values, &params);
- let cy = self.cy.get().normalize(values, &params);
- let rx = self.rx.get().normalize(values, &params);
- let ry = self.ry.get().normalize(values, &params);
+ let cx = self.cx.normalize(values, &params);
+ let cy = self.cy.normalize(values, &params);
+ let rx = self.rx.normalize(values, &params);
+ let ry = self.ry.normalize(values, &params);
render_ellipse(cx, cy, rx, ry, draw_ctx, node, values, clipping)
}
diff --git a/rsvg_internals/src/structure.rs b/rsvg_internals/src/structure.rs
index e35a325f..868bd772 100644
--- a/rsvg_internals/src/structure.rs
+++ b/rsvg_internals/src/structure.rs
@@ -1,6 +1,3 @@
-use std::cell::Cell;
-use std::cell::RefCell;
-
use cairo::Rectangle;
use markup5ever::local_name;
@@ -23,7 +20,7 @@ use crate::viewbox::*;
pub struct NodeGroup();
impl NodeTrait for NodeGroup {
- fn set_atts(&self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> NodeResult {
Ok(())
}
@@ -50,7 +47,7 @@ impl NodeTrait for NodeGroup {
pub struct NodeNonRendering;
impl NodeTrait for NodeNonRendering {
- fn set_atts(&self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> NodeResult {
Ok(())
}
}
@@ -59,7 +56,7 @@ impl NodeTrait for NodeNonRendering {
pub struct NodeSwitch();
impl NodeTrait for NodeSwitch {
- fn set_atts(&self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> NodeResult {
Ok(())
}
@@ -96,19 +93,19 @@ pub struct IntrinsicDimensions {
#[derive(Default)]
pub struct NodeSvg {
- preserve_aspect_ratio: Cell<AspectRatio>,
- x: Cell<Option<LengthHorizontal>>,
- y: Cell<Option<LengthVertical>>,
- w: Cell<Option<LengthHorizontal>>,
- h: Cell<Option<LengthVertical>>,
- vbox: Cell<Option<ViewBox>>,
+ preserve_aspect_ratio: AspectRatio,
+ x: Option<LengthHorizontal>,
+ y: Option<LengthVertical>,
+ w: Option<LengthHorizontal>,
+ h: Option<LengthVertical>,
+ vbox: Option<ViewBox>,
}
impl NodeSvg {
pub fn get_size(&self, values: &ComputedValues, dpi: Dpi) -> Option<(i32, i32)> {
let (_, _, w, h) = self.get_unnormalized_viewport();
- match (w, h, self.vbox.get()) {
+ match (w, h, self.vbox) {
(w, h, Some(vbox)) => {
let params = ViewParams::new(dpi.x(), dpi.y(), vbox.width, vbox.height);
@@ -132,9 +129,9 @@ impl NodeSvg {
pub fn get_intrinsic_dimensions(&self) -> IntrinsicDimensions {
IntrinsicDimensions {
- width: self.w.get(),
- height: self.h.get(),
- vbox: self.vbox.get(),
+ width: self.w,
+ height: self.h,
+ vbox: self.vbox,
}
}
@@ -150,19 +147,15 @@ impl NodeSvg {
// these defaults are per the spec
let x = self
.x
- .get()
.unwrap_or_else(|| LengthHorizontal::parse_str("0").unwrap());
let y = self
.y
- .get()
.unwrap_or_else(|| LengthVertical::parse_str("0").unwrap());
let w = self
.w
- .get()
.unwrap_or_else(|| LengthHorizontal::parse_str("100%").unwrap());
let h = self
.h
- .get()
.unwrap_or_else(|| LengthVertical::parse_str("100%").unwrap());
(x, y, w, h)
@@ -181,7 +174,7 @@ impl NodeSvg {
}
impl NodeTrait for NodeSvg {
- fn set_atts(&self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
// x & y attributes have no effect on outermost svg
// http://www.w3.org/TR/SVG/struct.html#SVGElement
let is_inner_svg = parent.is_some();
@@ -189,31 +182,19 @@ impl NodeTrait for NodeSvg {
for (attr, value) in pbag.iter() {
match attr {
local_name!("preserveAspectRatio") => {
- self.preserve_aspect_ratio.set(attr.parse(value)?)
+ self.preserve_aspect_ratio = attr.parse(value)?
}
-
- local_name!("x") => {
- if is_inner_svg {
- self.x.set(Some(attr.parse(value)?));
- }
+ local_name!("x") if is_inner_svg => self.x = Some(attr.parse(value)?),
+ local_name!("y") if is_inner_svg => self.y = Some(attr.parse(value)?),
+ local_name!("width") => {
+ self.w =
+ Some(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?)
}
-
- local_name!("y") => {
- if is_inner_svg {
- self.y.set(Some(attr.parse(value)?));
- }
+ local_name!("height") => {
+ self.h =
+ Some(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?)
}
-
- local_name!("width") => self.w.set(Some(
- attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?,
- )),
-
- local_name!("height") => self.h.set(Some(
- attr.parse_and_validate(value, LengthVertical::check_nonnegative)?,
- )),
-
- local_name!("viewBox") => self.vbox.set(attr.parse(value).map(Some)?),
-
+ local_name!("viewBox") => self.vbox = attr.parse(value).map(Some)?,
_ => (),
}
}
@@ -252,17 +233,17 @@ impl NodeTrait for NodeSvg {
// We are obtaining the toplevel SVG's geometry. This means, don't care about the
// DrawingCtx's viewport, just use the SVG's intrinsic dimensions and see how far
// it wants to extend.
- (svg_viewport, self.vbox.get())
+ (svg_viewport, self.vbox)
} else {
if has_parent {
- (svg_viewport, self.vbox.get())
+ (svg_viewport, self.vbox)
} else {
(
// The client's viewport overrides the toplevel's x/y/w/h viewport
draw_ctx.toplevel_viewport(),
// Use our viewBox if available, or try to derive one from
// the intrinsic dimensions.
- self.vbox.get().or_else(|| {
+ self.vbox.or_else(|| {
Some(ViewBox {
x: 0.0,
y: 0.0,
@@ -276,7 +257,7 @@ impl NodeTrait for NodeSvg {
draw_ctx.with_discrete_layer(node, values, clipping, &mut |dc| {
let _params =
- dc.push_new_viewport(vbox, &viewport, self.preserve_aspect_ratio.get(), clip_mode);
+ dc.push_new_viewport(vbox, &viewport, self.preserve_aspect_ratio, clip_mode);
node.draw_children(cascaded, dc, clipping)
})
@@ -285,33 +266,32 @@ impl NodeTrait for NodeSvg {
#[derive(Default)]
pub struct NodeUse {
- link: RefCell<Option<Fragment>>,
- x: Cell<LengthHorizontal>,
- y: Cell<LengthVertical>,
- w: Cell<Option<LengthHorizontal>>,
- h: Cell<Option<LengthVertical>>,
+ link: Option<Fragment>,
+ x: LengthHorizontal,
+ y: LengthVertical,
+ w: Option<LengthHorizontal>,
+ h: Option<LengthVertical>,
}
impl NodeTrait for NodeUse {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
local_name!("xlink:href") => {
- *self.link.borrow_mut() = Some(Fragment::parse(value).attribute(attr)?)
+ self.link = Some(Fragment::parse(value).attribute(attr)?)
+ }
+ local_name!("x") => self.x = attr.parse(value)?,
+ local_name!("y") => self.y = attr.parse(value)?,
+ local_name!("width") => {
+ self.w = attr
+ .parse_and_validate(value, LengthHorizontal::check_nonnegative)
+ .map(Some)?
+ }
+ local_name!("height") => {
+ self.h = attr
+ .parse_and_validate(value, LengthVertical::check_nonnegative)
+ .map(Some)?
}
-
- local_name!("x") => self.x.set(attr.parse(value)?),
- local_name!("y") => self.y.set(attr.parse(value)?),
-
- local_name!("width") => self.w.set(
- attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)
- .map(Some)?,
- ),
- local_name!("height") => self.h.set(
- attr.parse_and_validate(value, LengthVertical::check_nonnegative)
- .map(Some)?,
- ),
-
_ => (),
}
}
@@ -328,13 +308,11 @@ impl NodeTrait for NodeUse {
) -> Result<(), RenderingError> {
let values = cascaded.get();
- let link = self.link.borrow();
-
- if link.is_none() {
+ if self.link.is_none() {
return Ok(());
}
- let link = link.as_ref().unwrap();
+ let link = self.link.as_ref().unwrap();
let child = if let Some(acquired) = draw_ctx.acquired_nodes().get_node(link) {
// Here we clone the acquired child, so that we can drop the AcquiredNode as
@@ -355,8 +333,8 @@ impl NodeTrait for NodeUse {
let params = draw_ctx.get_view_params();
- let nx = self.x.get().normalize(values, &params);
- let ny = self.y.get().normalize(values, &params);
+ let nx = self.x.normalize(values, &params);
+ let ny = self.y.normalize(values, &params);
// If attributes ‘width’ and/or ‘height’ are not specified,
// [...] use values of '100%' for these attributes.
@@ -365,12 +343,10 @@ impl NodeTrait for NodeUse {
let nw = self
.w
- .get()
.unwrap_or_else(|| LengthHorizontal::parse_str("100%").unwrap())
.normalize(values, &params);
let nh = self
.h
- .get()
.unwrap_or_else(|| LengthVertical::parse_str("100%").unwrap())
.normalize(values, &params);
@@ -407,9 +383,9 @@ impl NodeTrait for NodeUse {
draw_ctx.with_discrete_layer(node, values, clipping, &mut |dc| {
let _params = dc.push_new_viewport(
- symbol.vbox.get(),
+ symbol.vbox,
&viewport,
- symbol.preserve_aspect_ratio.get(),
+ symbol.preserve_aspect_ratio,
clip_mode,
);
@@ -425,20 +401,18 @@ impl NodeTrait for NodeUse {
#[derive(Default)]
pub struct NodeSymbol {
- preserve_aspect_ratio: Cell<AspectRatio>,
- vbox: Cell<Option<ViewBox>>,
+ preserve_aspect_ratio: AspectRatio,
+ vbox: Option<ViewBox>,
}
impl NodeTrait for NodeSymbol {
- fn set_atts(&self, _parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
local_name!("preserveAspectRatio") => {
- self.preserve_aspect_ratio.set(attr.parse(value)?)
+ self.preserve_aspect_ratio = attr.parse(value)?
}
-
- local_name!("viewBox") => self.vbox.set(attr.parse(value).map(Some)?),
-
+ local_name!("viewBox") => self.vbox = attr.parse(value).map(Some)?,
_ => (),
}
}
diff --git a/rsvg_internals/src/style.rs b/rsvg_internals/src/style.rs
index 0df4fa4c..f0d83b1e 100644
--- a/rsvg_internals/src/style.rs
+++ b/rsvg_internals/src/style.rs
@@ -4,15 +4,13 @@ use crate::node::{NodeResult, NodeTrait, NodeType, RsvgNode};
use crate::property_bag::PropertyBag;
use crate::text::NodeChars;
-use std::cell::RefCell;
-
/// Represents a <style> node.
///
/// It does not render itself, and just holds CSS stylesheet information for the rest of
/// the code to use.
#[derive(Default)]
pub struct NodeStyle {
- type_: RefCell<Option<String>>,
+ type_: Option<String>,
}
impl NodeStyle {
@@ -26,12 +24,7 @@ impl NodeStyle {
// "contentStyleType" attribute of the svg element, which in turn
// defaults to "text/css".
- let have_css = self
- .type_
- .borrow()
- .as_ref()
- .map(|t| t == "text/css")
- .unwrap_or(true);
+ let have_css = self.type_.as_ref().map(|t| t == "text/css").unwrap_or(true);
if have_css {
node.children()
@@ -51,10 +44,10 @@ impl NodeStyle {
}
impl NodeTrait for NodeStyle {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
if attr == local_name!("type") {
- *self.type_.borrow_mut() = Some(value.to_string());
+ self.type_ = Some(value.to_string());
}
}
diff --git a/rsvg_internals/src/text.rs b/rsvg_internals/src/text.rs
index c56c4991..e9a4b3b9 100644
--- a/rsvg_internals/src/text.rs
+++ b/rsvg_internals/src/text.rs
@@ -3,7 +3,7 @@ use markup5ever::local_name;
use pango::{self, ContextExt, FontMapExt, LayoutExt};
use pango_sys;
use pangocairo;
-use std::cell::{Cell, RefCell};
+use std::cell::RefCell;
use crate::allowed_url::Fragment;
use crate::bbox::BoundingBox;
@@ -555,17 +555,17 @@ impl NodeChars {
}
impl NodeTrait for NodeChars {
- fn set_atts(&self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> NodeResult {
Ok(())
}
}
#[derive(Default)]
pub struct NodeText {
- x: Cell<LengthHorizontal>,
- y: Cell<LengthVertical>,
- dx: Cell<Option<LengthHorizontal>>,
- dy: Cell<Option<LengthVertical>>,
+ x: LengthHorizontal,
+ y: LengthVertical,
+ dx: Option<LengthHorizontal>,
+ dy: Option<LengthVertical>,
}
impl NodeText {
@@ -576,27 +576,20 @@ impl NodeText {
draw_ctx: &mut DrawingCtx,
) -> Vec<Chunk> {
let mut chunks = Vec::new();
-
- let x = self.x.get();
- let y = self.y.get();
- let dx = self.dx.get();
- let dy = self.dy.get();
-
- chunks.push(Chunk::new(cascaded.get(), Some(x), Some(y)));
-
- children_to_chunks(&mut chunks, node, cascaded, draw_ctx, dx, dy, 0);
+ chunks.push(Chunk::new(cascaded.get(), Some(self.x), Some(self.y)));
+ children_to_chunks(&mut chunks, node, cascaded, draw_ctx, self.dx, self.dy, 0);
chunks
}
}
impl NodeTrait for NodeText {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("x") => self.x.set(attr.parse(value)?),
- local_name!("y") => self.y.set(attr.parse(value)?),
- local_name!("dx") => self.dx.set(attr.parse(value).map(Some)?),
- local_name!("dy") => self.dy.set(attr.parse(value).map(Some)?),
+ local_name!("x") => self.x = attr.parse(value)?,
+ local_name!("y") => self.y = attr.parse(value)?,
+ local_name!("dx") => self.dx = attr.parse(value).map(Some)?,
+ local_name!("dy") => self.dy = attr.parse(value).map(Some)?,
_ => (),
}
}
@@ -614,8 +607,8 @@ impl NodeTrait for NodeText {
let values = cascaded.get();
let params = draw_ctx.get_view_params();
- let mut x = self.x.get().normalize(values, &params);
- let mut y = self.y.get().normalize(values, &params);
+ let mut x = self.x.normalize(values, &params);
+ let mut y = self.y.normalize(values, &params);
let chunks = self.make_chunks(node, cascaded, draw_ctx);
@@ -655,7 +648,7 @@ impl NodeTrait for NodeText {
#[derive(Default)]
pub struct NodeTRef {
- link: RefCell<Option<Fragment>>,
+ link: Option<Fragment>,
}
impl NodeTRef {
@@ -667,14 +660,11 @@ impl NodeTRef {
chunks: &mut Vec<Chunk>,
depth: usize,
) {
- let link = self.link.borrow();
-
- if link.is_none() {
+ if self.link.is_none() {
return;
}
- let link = link.as_ref().unwrap();
-
+ let link = self.link.as_ref().unwrap();
let values = cascaded.get();
if let Some(acquired) = draw_ctx.acquired_nodes().get_node(link) {
@@ -708,11 +698,11 @@ fn extract_chars_children_to_chunks_recursively(
}
impl NodeTrait for NodeTRef {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
local_name!("xlink:href") => {
- *self.link.borrow_mut() = Some(Fragment::parse(value).attribute(attr)?)
+ self.link = Some(Fragment::parse(value).attribute(attr)?)
}
_ => (),
}
@@ -724,10 +714,10 @@ impl NodeTrait for NodeTRef {
#[derive(Default)]
pub struct NodeTSpan {
- x: Cell<Option<LengthHorizontal>>,
- y: Cell<Option<LengthVertical>>,
- dx: Cell<Option<LengthHorizontal>>,
- dy: Cell<Option<LengthVertical>>,
+ x: Option<LengthHorizontal>,
+ y: Option<LengthVertical>,
+ dx: Option<LengthHorizontal>,
+ dy: Option<LengthVertical>,
}
impl NodeTSpan {
@@ -739,29 +729,24 @@ impl NodeTSpan {
chunks: &mut Vec<Chunk>,
depth: usize,
) {
- let x = self.x.get();
- let y = self.y.get();
- let dx = self.dx.get();
- let dy = self.dy.get();
-
- if x.is_some() || y.is_some() {
+ if self.x.is_some() || self.y.is_some() {
// Any absolute position creates a new chunk
let values = cascaded.get();
- chunks.push(Chunk::new(values, x, y));
+ chunks.push(Chunk::new(values, self.x, self.y));
}
- children_to_chunks(chunks, node, cascaded, draw_ctx, dx, dy, depth);
+ children_to_chunks(chunks, node, cascaded, draw_ctx, self.dx, self.dy, depth);
}
}
impl NodeTrait for NodeTSpan {
- fn set_atts(&self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- local_name!("x") => self.x.set(attr.parse(value).map(Some)?),
- local_name!("y") => self.y.set(attr.parse(value).map(Some)?),
- local_name!("dx") => self.dx.set(attr.parse(value).map(Some)?),
- local_name!("dy") => self.dy.set(attr.parse(value).map(Some)?),
+ local_name!("x") => self.x = attr.parse(value).map(Some)?,
+ local_name!("y") => self.y = attr.parse(value).map(Some)?,
+ local_name!("dx") => self.dx = attr.parse(value).map(Some)?,
+ local_name!("dy") => self.dy = attr.parse(value).map(Some)?,
_ => (),
}
}