diff options
author | Federico Mena Quintero <federico@gnome.org> | 2019-06-30 20:48:26 -0500 |
---|---|---|
committer | Federico Mena Quintero <federico@gnome.org> | 2019-06-30 20:48:26 -0500 |
commit | 2a83c10796ed4c7c25afe34769ae895dd01d7d96 (patch) | |
tree | 19158efb98a21698f143f4e61866125391c00d5d | |
parent | fd24ae31a234f28891b6bdf53867d73cebeeeb64 (diff) | |
parent | fc37026246bc521813fe62d8b783b0c2f8678a22 (diff) | |
download | librsvg-2a83c10796ed4c7c25afe34769ae895dd01d7d96.tar.gz |
Merge branch 'pborelli/librsvg-nointeriomut'
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, ¶ms), - y: self.y.get().normalize(values, ¶ms), - width: self.width.get().normalize(values, ¶ms), - height: self.height.get().normalize(values, ¶ms), + x: self.x.normalize(values, ¶ms), + y: self.y.normalize(values, ¶ms), + width: self.width.normalize(values, ¶ms), + height: self.height.normalize(values, ¶ms), } }; @@ -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, ¶ms); + 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, ¶ms), - v.y1.as_ref().unwrap().normalize(values, ¶ms), - v.x2.as_ref().unwrap().normalize(values, ¶ms), - v.y2.as_ref().unwrap().normalize(values, ¶ms), - ); - - 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, ¶ms); - let n_cy = v.cy.as_ref().unwrap().normalize(values, ¶ms); - let n_r = v.r.as_ref().unwrap().normalize(values, ¶ms); - let n_fx = v.fx.as_ref().unwrap().normalize(values, ¶ms); - let n_fy = v.fy.as_ref().unwrap().normalize(values, ¶ms); - - 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, ¶ms); - let y = self.y.get().normalize(values, ¶ms); - let w = self.w.get().normalize(values, ¶ms); - let h = self.h.get().normalize(values, ¶ms); + let x = self.x.normalize(values, ¶ms); + let y = self.y.normalize(values, ¶ms); + let w = self.w.normalize(values, ¶ms); + let h = self.h.normalize(values, ¶ms); 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, ¶ms); - let marker_height = self.height.get().normalize(&values, ¶ms); + let marker_width = self.width.normalize(&values, ¶ms); + let marker_height = self.height.normalize(&values, ¶ms); 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, ¶ms), - -self.ref_y.get().normalize(&values, ¶ms), + -self.ref_x.normalize(&values, ¶ms), + -self.ref_y.normalize(&values, ¶ms), ); 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, ¶ms); - let y = self.y.get().normalize(&values, ¶ms); - let w = self.width.get().normalize(&values, ¶ms); - let h = self.height.get().normalize(&values, ¶ms); + let x = self.x.normalize(&values, ¶ms); + let y = self.y.normalize(&values, ¶ms); + let w = self.width.normalize(&values, ¶ms); + let h = self.height.normalize(&values, ¶ms); (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, ¶ms); - let y1 = self.y1.get().normalize(values, ¶ms); - let x2 = self.x2.get().normalize(values, ¶ms); - let y2 = self.y2.get().normalize(values, ¶ms); + let x1 = self.x1.normalize(values, ¶ms); + let y1 = self.y1.normalize(values, ¶ms); + let x2 = self.x2.normalize(values, ¶ms); + let y2 = self.y2.normalize(values, ¶ms); 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, ¶ms); - let y = self.y.get().normalize(values, ¶ms); - let w = self.w.get().normalize(values, ¶ms); - let h = self.h.get().normalize(values, ¶ms); + let x = self.x.normalize(values, ¶ms); + let y = self.y.normalize(values, ¶ms); + let w = self.w.normalize(values, ¶ms); + let h = self.h.normalize(values, ¶ms); 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, ¶ms); - let cy = self.cy.get().normalize(values, ¶ms); - let r = self.r.get().normalize(values, ¶ms); + let cx = self.cx.normalize(values, ¶ms); + let cy = self.cy.normalize(values, ¶ms); + let r = self.r.normalize(values, ¶ms); 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, ¶ms); - let cy = self.cy.get().normalize(values, ¶ms); - let rx = self.rx.get().normalize(values, ¶ms); - let ry = self.ry.get().normalize(values, ¶ms); + let cx = self.cx.normalize(values, ¶ms); + let cy = self.cy.normalize(values, ¶ms); + let rx = self.rx.normalize(values, ¶ms); + let ry = self.ry.normalize(values, ¶ms); 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, ¶ms); - let ny = self.y.get().normalize(values, ¶ms); + let nx = self.x.normalize(values, ¶ms); + let ny = self.y.normalize(values, ¶ms); // 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, ¶ms); let nh = self .h - .get() .unwrap_or_else(|| LengthVertical::parse_str("100%").unwrap()) .normalize(values, ¶ms); @@ -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, ¶ms); - let mut y = self.y.get().normalize(values, ¶ms); + let mut x = self.x.normalize(values, ¶ms); + let mut y = self.y.normalize(values, ¶ms); 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)?, _ => (), } } |