diff options
author | Evgeniy Reizner <razrfalcon@gmail.com> | 2019-08-15 16:57:25 +0300 |
---|---|---|
committer | Evgeniy Reizner <razrfalcon@gmail.com> | 2019-08-15 16:57:25 +0300 |
commit | 8dddb2cba29559a7782c2839b8472fe0677c8865 (patch) | |
tree | 4689cfdeb528fe0740f0e68b7a62c462651df63c | |
parent | 0d66a9cda4c69444c7874aebf6d92d4bc0075fac (diff) |
Use Rc for path data.
-rw-r--r-- | usvg/src/convert/marker.rs | 3 | ||||
-rw-r--r-- | usvg/src/convert/mod.rs | 2 | ||||
-rw-r--r-- | usvg/src/convert/shapes.rs | 32 | ||||
-rw-r--r-- | usvg/src/convert/text/convert.rs | 4 | ||||
-rw-r--r-- | usvg/src/convert/text/mod.rs | 18 | ||||
-rw-r--r-- | usvg/src/convert/use_node.rs | 4 | ||||
-rw-r--r-- | usvg/src/svgtree/mod.rs | 5 | ||||
-rw-r--r-- | usvg/src/svgtree/parse.rs | 3 | ||||
-rw-r--r-- | usvg/src/tree/nodes.rs | 5 | ||||
-rw-r--r-- | usvg/src/tree/pathdata.rs | 8 |
10 files changed, 51 insertions, 33 deletions
diff --git a/usvg/src/convert/marker.rs b/usvg/src/convert/marker.rs index 4b1453e..fd2bcbe 100644 --- a/usvg/src/convert/marker.rs +++ b/usvg/src/convert/marker.rs @@ -3,6 +3,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. use std::f64; +use std::rc::Rc; use crate::{utils, svgtree, tree, tree::prelude::*, tree::PathSegment as Segment}; use super::{prelude::*, use_node}; @@ -114,7 +115,7 @@ fn resolve( clip_path.append_kind(tree::NodeKind::Path(tree::Path { fill: Some(tree::Fill::default()), - data: tree::PathData::from_rect(clip_rect), + data: Rc::new(tree::PathData::from_rect(clip_rect)), ..tree::Path::default() })); diff --git a/usvg/src/convert/mod.rs b/usvg/src/convert/mod.rs index dddff1a..57bc3ad 100644 --- a/usvg/src/convert/mod.rs +++ b/usvg/src/convert/mod.rs @@ -565,7 +565,7 @@ fn remove_unused_defs( fn convert_path( node: svgtree::Node, - path: tree::PathData, + path: tree::SharedPathData, state: &State, parent: &mut tree::Node, tree: &mut tree::Tree, diff --git a/usvg/src/convert/shapes.rs b/usvg/src/convert/shapes.rs index a83f98d..dfb69f9 100644 --- a/usvg/src/convert/shapes.rs +++ b/usvg/src/convert/shapes.rs @@ -2,6 +2,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use std::rc::Rc; + use crate::{svgtree, tree}; use super::{prelude::*, units}; @@ -9,7 +11,7 @@ use super::{prelude::*, units}; pub fn convert( node: svgtree::Node, state: &State, -) -> Option<tree::PathData> { +) -> Option<tree::SharedPathData> { match node.tag_name()? { EId::Rect => convert_rect(node, state), EId::Circle => convert_circle(node, state), @@ -24,14 +26,14 @@ pub fn convert( pub fn convert_path( node: svgtree::Node, -) -> Option<tree::PathData> { - node.attribute::<tree::PathData>(AId::D) +) -> Option<tree::SharedPathData> { + node.attribute::<tree::SharedPathData>(AId::D) } pub fn convert_rect( node: svgtree::Node, state: &State, -) -> Option<tree::PathData> { +) -> Option<tree::SharedPathData> { // 'width' and 'height' attributes must be positive and non-zero. let width = node.convert_user_length(AId::Width, state, Length::zero()); let height = node.convert_user_length(AId::Height, state, Length::zero()); @@ -107,13 +109,13 @@ pub fn convert_rect( p }; - Some(path) + Some(Rc::new(path)) } pub fn convert_line( node: svgtree::Node, state: &State, -) -> Option<tree::PathData> { +) -> Option<tree::SharedPathData> { let x1 = node.convert_user_length(AId::X1, state, Length::zero()); let y1 = node.convert_user_length(AId::Y1, state, Length::zero()); let x2 = node.convert_user_length(AId::X2, state, Length::zero()); @@ -122,21 +124,21 @@ pub fn convert_line( let mut path = tree::PathData::new(); path.push_move_to(x1, y1); path.push_line_to(x2, y2); - Some(path) + Some(Rc::new(path)) } pub fn convert_polyline( node: svgtree::Node, -) -> Option<tree::PathData> { - points_to_path(node, "Polyline") +) -> Option<tree::SharedPathData> { + points_to_path(node, "Polyline").map(Rc::new) } pub fn convert_polygon( node: svgtree::Node, -) -> Option<tree::PathData> { +) -> Option<tree::SharedPathData> { if let Some(mut path) = points_to_path(node, "Polygon") { path.push(tree::PathSegment::ClosePath); - Some(path) + Some(Rc::new(path)) } else { None } @@ -177,7 +179,7 @@ fn points_to_path( pub fn convert_circle( node: svgtree::Node, state: &State, -) -> Option<tree::PathData> { +) -> Option<tree::SharedPathData> { let cx = node.convert_user_length(AId::Cx, state, Length::zero()); let cy = node.convert_user_length(AId::Cy, state, Length::zero()); let r = node.convert_user_length(AId::R, state, Length::zero()); @@ -187,13 +189,13 @@ pub fn convert_circle( return None; } - Some(ellipse_to_path(cx, cy, r, r)) + Some(Rc::new(ellipse_to_path(cx, cy, r, r))) } pub fn convert_ellipse( node: svgtree::Node, state: &State, -) -> Option<tree::PathData> { +) -> Option<tree::SharedPathData> { let cx = node.convert_user_length(AId::Cx, state, Length::zero()); let cy = node.convert_user_length(AId::Cy, state, Length::zero()); let rx = node.convert_user_length(AId::Rx, state, Length::zero()); @@ -209,7 +211,7 @@ pub fn convert_ellipse( return None; } - Some(ellipse_to_path(cx, cy, rx, ry)) + Some(Rc::new(ellipse_to_path(cx, cy, rx, ry))) } fn ellipse_to_path( diff --git a/usvg/src/convert/text/convert.rs b/usvg/src/convert/text/convert.rs index 9ebcd03..0cbd67c 100644 --- a/usvg/src/convert/text/convert.rs +++ b/usvg/src/convert/text/convert.rs @@ -59,7 +59,7 @@ pub struct TextPath { /// Percentage values already resolved. pub start_offset: f64, - pub path: tree::PathData, + pub path: tree::SharedPathData, } @@ -308,7 +308,7 @@ fn resolve_text_flow( return None; } - let path = path_node.attribute::<tree::PathData>(AId::D)?; + let path = path_node.attribute::<tree::SharedPathData>(AId::D)?; let start_offset: Length = node.attribute(AId::StartOffset).unwrap_or_default(); let start_offset = if start_offset.unit == Unit::Percent { diff --git a/usvg/src/convert/text/mod.rs b/usvg/src/convert/text/mod.rs index b00554e..aa756be 100644 --- a/usvg/src/convert/text/mod.rs +++ b/usvg/src/convert/text/mod.rs @@ -2,6 +2,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use std::rc::Rc; + use crate::{svgtree, tree, tree::prelude::*}; use super::prelude::*; @@ -201,7 +203,7 @@ fn convert_span( parent: &mut tree::Node, dump_clusters: bool, ) -> Option<tree::Path> { - let mut data = tree::PathData::new(); + let mut path_data = tree::PathData::new(); for cluster in clusters { if !cluster.visible { @@ -218,11 +220,11 @@ fn convert_span( let mut path = std::mem::replace(&mut cluster.path, tree::PathData::new()); path.transform(cluster.transform); - data.extend_from_slice(&path); + path_data.extend_from_slice(&path); } } - if data.is_empty() { + if path_data.is_empty() { return None; } @@ -243,7 +245,7 @@ fn convert_span( fill, stroke: span.stroke.take(), rendering_mode: tree::ShapeRendering::default(), - data, + data: Rc::new(path_data), }; Some(path) @@ -271,15 +273,15 @@ fn dump_cluster( // Cluster bbox. let r = Rect::new(0.0, -cluster.ascent, cluster.advance, cluster.height()).unwrap(); base_path.stroke = new_stroke(tree::Color::blue()); - base_path.data = tree::PathData::from_rect(r); + base_path.data = Rc::new(tree::PathData::from_rect(r)); parent.append_kind(tree::NodeKind::Path(base_path.clone())); // Baseline. base_path.stroke = new_stroke(tree::Color::red()); - base_path.data = tree::PathData(vec![ + base_path.data = Rc::new(tree::PathData(vec![ tree::PathSegment::MoveTo { x: 0.0, y: 0.0 }, tree::PathSegment::LineTo { x: cluster.advance, y: 0.0 }, - ]); + ])); parent.append_kind(tree::NodeKind::Path(base_path)); } @@ -354,7 +356,7 @@ fn convert_decoration( fill: decoration.fill.take(), stroke: decoration.stroke.take(), rendering_mode: tree::ShapeRendering::default(), - data: path, + data: Rc::new(path), } } diff --git a/usvg/src/convert/use_node.rs b/usvg/src/convert/use_node.rs index 2ad8215..23885a2 100644 --- a/usvg/src/convert/use_node.rs +++ b/usvg/src/convert/use_node.rs @@ -2,6 +2,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use std::rc::Rc; + use crate::{svgtree, tree, tree::prelude::*, utils}; use super::prelude::*; @@ -119,7 +121,7 @@ fn clip_element( clip_path.append_kind(tree::NodeKind::Path(tree::Path { fill: Some(tree::Fill::default()), - data: tree::PathData::from_rect(clip_rect), + data: Rc::new(tree::PathData::from_rect(clip_rect)), ..tree::Path::default() })); diff --git a/usvg/src/svgtree/mod.rs b/usvg/src/svgtree/mod.rs index 6b93be5..61dfe3a 100644 --- a/usvg/src/svgtree/mod.rs +++ b/usvg/src/svgtree/mod.rs @@ -157,7 +157,7 @@ pub enum AttributeValue { NumberList(svgtypes::NumberList), Opacity(tree::Opacity), Paint(String, Option<svgtypes::PaintFallback>), - Path(tree::PathData), + Path(tree::SharedPathData), String(String), Transform(svgtypes::Transform), ViewBox(svgtypes::ViewBox), @@ -652,9 +652,10 @@ impl<'a> FromValue<'a> for svgtypes::Transform { } } -impl FromValue<'_> for tree::PathData { +impl FromValue<'_> for tree::SharedPathData { fn get(node: Node, aid: AId) -> Option<Self> { let a = node.attributes().iter().find(|a| a.name == aid)?; + // Cloning is cheap, since it's a Rc. if let AttributeValue::Path(ref v) = a.value { Some(v.clone()) } else { None } } } diff --git a/usvg/src/svgtree/parse.rs b/usvg/src/svgtree/parse.rs index 2c58e7d..bcc8b0f 100644 --- a/usvg/src/svgtree/parse.rs +++ b/usvg/src/svgtree/parse.rs @@ -2,6 +2,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use std::rc::Rc; use std::str::FromStr; use std::collections::HashMap; @@ -451,7 +452,7 @@ fn parse_svg_attribute( AId::D => { let segments = parse_path(value); if segments.len() >= 2 { - AttributeValue::Path(segments) + AttributeValue::Path(Rc::new(segments)) } else { return Err(svgtypes::Error::InvalidValue); } diff --git a/usvg/src/tree/nodes.rs b/usvg/src/tree/nodes.rs index 0fb35e6..71c4c54 100644 --- a/usvg/src/tree/nodes.rs +++ b/usvg/src/tree/nodes.rs @@ -3,6 +3,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. use std::ops::Deref; +use std::rc::Rc; use crate::geom::*; use super::attributes::*; @@ -120,7 +121,7 @@ pub struct Path { /// Segments list. /// /// All segments are in absolute coordinates. - pub data: PathData, + pub data: Rc<PathData>, } impl Default for Path { @@ -132,7 +133,7 @@ impl Default for Path { fill: None, stroke: None, rendering_mode: ShapeRendering::default(), - data: PathData::default(), + data: Rc::new(PathData::default()), } } } diff --git a/usvg/src/tree/pathdata.rs b/usvg/src/tree/pathdata.rs index eb79238..703492d 100644 --- a/usvg/src/tree/pathdata.rs +++ b/usvg/src/tree/pathdata.rs @@ -2,6 +2,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use std::rc::Rc; + use svgtypes::FuzzyZero; use kurbo::{ParamCurveArclen, ParamCurveExtrema}; @@ -42,6 +44,12 @@ pub enum PathSegment { #[derive(Clone, Default, Debug)] pub struct PathData(pub Vec<PathSegment>); +/// A reference-counted `PathData`. +/// +/// `PathData` is usually pretty big and it's expensive to clone it, +/// so we are using `Rc`. +pub type SharedPathData = Rc<PathData>; + impl PathData { /// Creates a new path. #[inline] |