summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeniy Reizner <razrfalcon@gmail.com>2019-08-15 16:57:25 +0300
committerEvgeniy Reizner <razrfalcon@gmail.com>2019-08-15 16:57:25 +0300
commit8dddb2cba29559a7782c2839b8472fe0677c8865 (patch)
tree4689cfdeb528fe0740f0e68b7a62c462651df63c
parent0d66a9cda4c69444c7874aebf6d92d4bc0075fac (diff)
Use Rc for path data.
-rw-r--r--usvg/src/convert/marker.rs3
-rw-r--r--usvg/src/convert/mod.rs2
-rw-r--r--usvg/src/convert/shapes.rs32
-rw-r--r--usvg/src/convert/text/convert.rs4
-rw-r--r--usvg/src/convert/text/mod.rs18
-rw-r--r--usvg/src/convert/use_node.rs4
-rw-r--r--usvg/src/svgtree/mod.rs5
-rw-r--r--usvg/src/svgtree/parse.rs3
-rw-r--r--usvg/src/tree/nodes.rs5
-rw-r--r--usvg/src/tree/pathdata.rs8
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]