diff --git a/examples/count_curveto_segments.rs b/examples/count_curveto_segments.rs
index a30316d..864b610 100644
@@ -28,7 +28,8 @@ fn main() {
for node in doc.descendants().svg() {
let attrs = node.attributes();
if let Some(&AttributeValue::Path(ref path)) = attrs.get_value(AttributeId::D) {
- count += path.d.iter().filter(|seg| seg.cmd() == Command::CurveTo).count();
+ // We have to borrow the path content, because it behind `Rc`.
+ count += path.borrow().iter().filter(|seg| seg.cmd() == Command::CurveTo).count();
}
}
diff --git a/src/attribute/attribute_value.rs b/src/attribute/attribute_value.rs
index 22f080e..09600fc 100644
@@ -13,12 +13,12 @@ use {
WriteToString,
};
use types::{
+ path,
Color,
Length,
LengthList,
LengthUnit,
NumberList,
- path,
Transform,
};
@@ -162,6 +162,7 @@ impl AttributeValue {
}
}
+ // TODO: remove
/// Returns type's name. For the debug purposes.
pub fn name(&self) -> &str {
match *self {
@@ -190,13 +191,13 @@ impl WriteBuffer for AttributeValue {
n.write_buf_opt(opt, buf);
},
AttributeValue::NumberList(ref list) => {
- write_list(list, opt, buf)
+ write_list(&list.borrow(), opt, buf)
},
AttributeValue::Length(ref l) => {
l.write_buf_opt(opt, buf);
},
AttributeValue::LengthList(ref list) => {
- write_list(list, opt, buf);
+ write_list(&list.borrow(), opt, buf);
},
AttributeValue::Transform(ref t) => {
t.write_buf_opt(opt, buf);
diff --git a/src/lib.rs b/src/lib.rs
index a33a92e..45858e8 100644
@@ -50,7 +50,6 @@ DOM structure itself based on: https://github.com/SimonSapin/rust-forest/tree/ma
*/
#![warn(missing_docs)]
-#![deny(unused_import_braces)]
#[macro_use]
extern crate svgparser;
diff --git a/src/parser/parser.rs b/src/parser/parser.rs
index 4edc397..3210884 100644
@@ -36,7 +36,9 @@ use types::{
path,
Color,
Length,
+ LengthList,
LengthUnit,
+ NumberList,
Transform,
};
@@ -456,7 +458,7 @@ fn parse_svg_attribute_value<'a>(
}
if !vec.is_empty() {
- Some(AttributeValue::NumberList(vec))
+ Some(AttributeValue::NumberList(NumberList::new(vec)))
} else {
None
}
@@ -474,7 +476,7 @@ fn parse_svg_attribute_value<'a>(
}
if !vec.is_empty() {
- Some(AttributeValue::LengthList(vec))
+ Some(AttributeValue::LengthList(LengthList::new(vec)))
} else {
None
}
diff --git a/src/postproc/fix_attrs.rs b/src/postproc/fix_attrs.rs
index 6391b00..669a419 100644
@@ -106,7 +106,8 @@ pub fn fix_poly_attributes(node: &Node) {
let mut is_empty = false;
if let Some(points_value) = attrs_data.get_value_mut(AttributeId::Points) {
- if let AttributeValue::NumberList(ref mut p) = *points_value {
+ if let AttributeValue::NumberList(ref p) = *points_value {
+ let mut p = p.borrow_mut();
if p.is_empty() {
// remove if no points
is_empty = true;
diff --git a/src/types/mod.rs b/src/types/mod.rs
index ab335b1..edd469a 100644
@@ -4,20 +4,22 @@
//! This module contains submodules which represent SVG value types.
-pub use self::transform::Transform;
pub use self::color::Color;
pub use self::length::Length;
pub use self::number::{FuzzyEq, FuzzyOrd};
+pub use self::rcvec::RcVec;
+pub use self::transform::Transform;
pub use svgparser::LengthUnit;
/// Representation of the `<list-of-numbers>` type.
-pub type NumberList = Vec<f64>;
+pub type NumberList = RcVec<f64>;
/// Representation of the `<list-of-lengths>` type.
-pub type LengthList = Vec<Length>;
+pub type LengthList = RcVec<Length>;
pub mod path;
mod color;
mod length;
mod number;
+mod rcvec;
mod transform;
diff --git a/src/types/path/builder.rs b/src/types/path/builder.rs
index 7b98221..3f90ca6 100644
@@ -10,85 +10,85 @@ use super::{
/// Construct a new path using build pattern.
#[derive(Default)]
pub struct Builder {
- path: Path,
+ path: Vec<Segment>,
}
impl Builder {
/// Constructs a new builder.
pub fn new() -> Builder {
- Builder { path: Path::new() }
+ Builder { path: Vec::new() }
}
/// Constructs a new builder with the specified capacity.
pub fn with_capacity(capacity: usize) -> Builder {
- Builder { path: Path::with_capacity(capacity) }
+ Builder { path: Vec::with_capacity(capacity) }
}
// TODO: from existing Path
/// Appends a new MoveTo segment.
pub fn move_to(mut self, x: f64, y: f64) -> Builder {
- self.path.d.push(Segment::new_move_to(x, y));
+ self.path.push(Segment::new_move_to(x, y));
self
}
/// Appends a new ClosePath segment.
pub fn close_path(mut self) -> Builder {
- self.path.d.push(Segment::new_close_path());
+ self.path.push(Segment::new_close_path());
self
}
/// Appends a new LineTo segment.
pub fn line_to(mut self, x: f64, y: f64) -> Builder {
- self.path.d.push(Segment::new_line_to(x, y));
+ self.path.push(Segment::new_line_to(x, y));
self
}
/// Appends a new HorizontalLineTo segment.
pub fn hline_to(mut self, x: f64) -> Builder {
- self.path.d.push(Segment::new_hline_to(x));
+ self.path.push(Segment::new_hline_to(x));
self
}
/// Appends a new VerticalLineTo segment.
pub fn vline_to(mut self, y: f64) -> Builder {
- self.path.d.push(Segment::new_vline_to(y));
+ self.path.push(Segment::new_vline_to(y));
self
}
/// Appends a new CurveTo segment.
pub fn curve_to(mut self, x1: f64, y1: f64, x2: f64, y2: f64, x: f64, y: f64) -> Builder {
- self.path.d.push(Segment::new_curve_to(x1, y1, x2, y2, x, y));
+ self.path.push(Segment::new_curve_to(x1, y1, x2, y2, x, y));
self
}
/// Appends a new SmoothCurveTo segment.
pub fn smooth_curve_to(mut self, x2: f64, y2: f64, x: f64, y: f64) -> Builder {
- self.path.d.push(Segment::new_smooth_curve_to(x2, y2, x, y));
+ self.path.push(Segment::new_smooth_curve_to(x2, y2, x, y));
self
}
/// Appends a new QuadTo segment.
pub fn quad_to(mut self, x1: f64, y1: f64, x: f64, y: f64) -> Builder {
- self.path.d.push(Segment::new_quad_to(x1, y1, x, y));
+ self.path.push(Segment::new_quad_to(x1, y1, x, y));
self
}
/// Appends a new SmoothQuadTo segment.
pub fn smooth_quad_to(mut self, x: f64, y: f64) -> Builder {
- self.path.d.push(Segment::new_smooth_quad_to(x, y));
+ self.path.push(Segment::new_smooth_quad_to(x, y));
self
}
/// Appends a new ArcTo segment.
pub fn arc_to(mut self, rx: f64, ry: f64, x_axis_rotation: f64, large_arc: bool, sweep: bool,
x: f64, y: f64) -> Builder {
- self.path.d.push(Segment::new_arc_to(rx, ry, x_axis_rotation, large_arc, sweep, x, y));
+ self.path.push(Segment::new_arc_to(rx, ry, x_axis_rotation, large_arc, sweep, x, y));
self
}
/// Finalizes the build.
pub fn finalize(self) -> Path {
- self.path
+ Path::from_vec(self.path)
}
}
diff --git a/src/types/path/parser.rs b/src/types/path/parser.rs
index 8802815..be2a6f8 100644
@@ -28,7 +28,7 @@ impl FromStream for Path {
use svgparser::path::Token;
let mut t = svgparser::path::Tokenizer::from_frame(s);
- let mut p = Path::new();
+ let mut v = Vec::new();
loop {
let seg = match t.parse_next()? {
@@ -102,9 +102,9 @@ impl FromStream for Path {
}
};
- p.d.push(seg);
+ v.push(seg);
}
- Ok(p)
+ Ok(Path::from_vec(v))
}
}
diff --git a/src/types/path/path.rs b/src/types/path/path.rs
index 4df80dc..3291242 100644
@@ -7,6 +7,15 @@ use std::{
str,
};
+use std::cell::{
+ Ref,
+ RefMut,
+};
+
+use types::{
+ RcVec,
+};
+
use super::{
Command,
Segment,
@@ -14,21 +23,25 @@ use super::{
};
/// Representation of the SVG path data.
-#[derive(Default,PartialEq,Clone)]
+#[derive(PartialEq,Clone)]
pub struct Path {
- /// Vector which contain all segments.
- pub d: Vec<Segment>
+ d: RcVec<Segment>
}
impl Path {
/// Constructs a new path.
- pub fn new() -> Path {
- Path { d: Vec::new() }
+ pub fn from_vec(v: Vec<Segment>) -> Path {
+ Path { d: RcVec::new(v) }
+ }
+
+ /// Returns a borrowed content.
+ pub fn borrow(&self) -> Ref<Vec<Segment>> {
+ self.d.borrow()
}
- /// Constructs a new path with the specified capacity.
- pub fn with_capacity(capacity: usize) -> Path {
- Path { d: Vec::with_capacity(capacity) }
+ /// Returns a mutability borrowed content.
+ pub fn borrow_mut(&self) -> RefMut<Vec<Segment>> {
+ self.d.borrow_mut()
}
// TODO: append Path
@@ -48,7 +61,7 @@ impl Path {
let mut prev_my = 0.0;
let mut prev_cmd = Command::MoveTo;
- for seg in &mut self.d {
+ for seg in self.d.borrow_mut().iter_mut() {
if seg.cmd() == Command::ClosePath {
prev_x = prev_mx;
prev_y = prev_my;
@@ -113,7 +126,7 @@ impl Path {
let mut prev_my = 0.0;
let mut prev_cmd = Command::MoveTo;
- for seg in &mut self.d {
+ for seg in self.d.borrow_mut().iter_mut() {
if seg.cmd() == Command::ClosePath {
prev_x = prev_mx;
prev_y = prev_my;
diff --git a/src/types/path/writer.rs b/src/types/path/writer.rs
index 4571395..067f020 100644
@@ -27,14 +27,14 @@ struct PrevCmd {
impl WriteBuffer for Path {
fn write_buf_opt(&self, opt: &WriteOptions, buf: &mut Vec<u8>) {
- if self.d.is_empty() {
+ if self.borrow().is_empty() {
return;
}
let mut prev_cmd: Option<PrevCmd> = None;
let mut prev_coord_has_dot = false;
- for seg in &self.d {
+ for seg in self.borrow().iter() {
let is_written = write_cmd(seg, &mut prev_cmd, opt, buf);
write_segment(seg.data(), is_written, &mut prev_coord_has_dot, opt, buf);
}
@@ -258,10 +258,10 @@ mod tests {
#[test]
fn gen_path_1() {
- let mut path = Path::new();
- path.d.push(Segment::new_move_to(10.0, 20.0));
- path.d.push(Segment::new_line_to(10.0, 20.0));
- assert_eq!(path.to_string(), "M 10 20 L 10 20");
+ let mut v = Vec::new();
+ v.push(Segment::new_move_to(10.0, 20.0));
+ v.push(Segment::new_line_to(10.0, 20.0));
+ assert_eq!(Path::from_vec(v).to_string(), "M 10 20 L 10 20");
}
#[test]
diff --git a/tests/writer.rs b/tests/writer.rs
index e113f10..55914f3 100644
@@ -17,7 +17,9 @@ use svgdom::{
use svgdom::types::{
Color,
Length,
+ LengthList,
LengthUnit,
+ NumberList,
Transform,
};
@@ -149,13 +151,13 @@ fn attributes_types_1() {
svg.set_attribute((AId::Height, Length::new(1.5, LengthUnit::Percent)));
svg.set_attribute((AId::Fill, Color::new(255, 255, 255)));
svg.set_attribute((AId::Transform, Transform::new(2.0, 0.0, 0.0, 3.0, 20.0, 30.0)));
- svg.set_attribute((AId::StdDeviation, vec![1.5, 2.5, 3.5]));
+ svg.set_attribute((AId::StdDeviation, NumberList::new(vec![1.5, 2.5, 3.5])));
let mut len_list = Vec::new();
len_list.push(Length::new(1.5, LengthUnit::Mm));
len_list.push(Length::new(2.5, LengthUnit::Mm));
len_list.push(Length::new(3.5, LengthUnit::Mm));
- svg.set_attribute((AId::StrokeDasharray, len_list));
+ svg.set_attribute((AId::StrokeDasharray, LengthList::new(len_list)));
// TODO: add path