diff options
author | Reizner Evgeniy <razrfalcon@gmail.com> | 2018-02-22 17:59:38 +0200 |
---|---|---|
committer | Reizner Evgeniy <razrfalcon@gmail.com> | 2018-02-22 17:59:38 +0200 |
commit | 36a08050811373d443c4ac6a9ef3f2e1de083ae6 (patch) | |
tree | 0050ecdd0902424d97c985012c720d484be7a9df | |
parent | ecd403f9204a306b39e98ee9d8e0fa4aaf18a818 (diff) |
Reduced RenderTree propagation thanks to new ero_tree tree() method.
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | capi/src/lib.rs | 1 | ||||
-rw-r--r-- | examples/draw_bboxes.rs | 5 | ||||
-rw-r--r-- | src/convert/clippath.rs | 4 | ||||
-rw-r--r-- | src/convert/fill.rs | 2 | ||||
-rw-r--r-- | src/convert/gradient.rs | 6 | ||||
-rw-r--r-- | src/convert/image.rs | 2 | ||||
-rw-r--r-- | src/convert/mod.rs | 4 | ||||
-rw-r--r-- | src/convert/path.rs | 2 | ||||
-rw-r--r-- | src/convert/pattern.rs | 4 | ||||
-rw-r--r-- | src/convert/stroke.rs | 2 | ||||
-rw-r--r-- | src/convert/text.rs | 2 | ||||
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/render_cairo/clippath.rs | 5 | ||||
-rw-r--r-- | src/render_cairo/fill.rs | 7 | ||||
-rw-r--r-- | src/render_cairo/mod.rs | 44 | ||||
-rw-r--r-- | src/render_cairo/pattern.rs | 3 | ||||
-rw-r--r-- | src/render_cairo/stroke.rs | 4 | ||||
-rw-r--r-- | src/render_cairo/text.rs | 15 | ||||
-rw-r--r-- | src/render_qt/clippath.rs | 5 | ||||
-rw-r--r-- | src/render_qt/fill.rs | 4 | ||||
-rw-r--r-- | src/render_qt/mod.rs | 34 | ||||
-rw-r--r-- | src/render_qt/pattern.rs | 3 | ||||
-rw-r--r-- | src/render_qt/stroke.rs | 4 | ||||
-rw-r--r-- | src/render_qt/text.rs | 15 | ||||
-rw-r--r-- | src/tree/mod.rs | 107 | ||||
-rw-r--r-- | tools/rendersvg/src/main.rs | 6 |
27 files changed, 136 insertions, 159 deletions
@@ -20,7 +20,8 @@ libflate = "0.1" # lyon_geom = "0.9" lyon_geom = { git = "https://github.com/nical/lyon.git" } euclid = "0.17" -ego-tree = "0.2" +# ego-tree = "0.2" +ego-tree = { git = "https://github.com/programble/ego-tree" } [dependencies.error-chain] version = "0.11" diff --git a/capi/src/lib.rs b/capi/src/lib.rs index bac7491..d062460 100644 --- a/capi/src/lib.rs +++ b/capi/src/lib.rs @@ -28,6 +28,7 @@ use resvg::qt; use resvg::cairo; use resvg::RectExt; +use resvg::tree::prelude::*; #[repr(C)] pub struct Rect { diff --git a/examples/draw_bboxes.rs b/examples/draw_bboxes.rs index 6550fe8..5fb7d4a 100644 --- a/examples/draw_bboxes.rs +++ b/examples/draw_bboxes.rs @@ -4,11 +4,10 @@ use std::env; use std::path::Path; use resvg::{ - tree, utils, Options, - NodeExt, }; +use resvg::tree::prelude::*; // TODO: write doc @@ -42,7 +41,7 @@ fn main() { let mut bboxes = Vec::new(); for node in rtree.root().descendants() { if !rtree.is_in_defs(node) { - if let Some(bbox) = backend.calc_node_bbox(&rtree, node, &opt) { + if let Some(bbox) = backend.calc_node_bbox(node, &opt) { bboxes.push(bbox); } } diff --git a/src/convert/clippath.rs b/src/convert/clippath.rs index fbe944d..ae9abde 100644 --- a/src/convert/clippath.rs +++ b/src/convert/clippath.rs @@ -6,7 +6,7 @@ use svgdom; // self -use tree; +use tree::prelude::*; use short::{ AId, EId, @@ -27,7 +27,7 @@ pub fn convert( ) { let attrs = node.attributes(); - let clip_node = rtree.append_defs( + let clip_node = rtree.append_to_defs( tree::NodeKind::ClipPath(tree::ClipPath { id: node.id().clone(), units: super::convert_element_units(&attrs, AId::ClipPathUnits), diff --git a/src/convert/fill.rs b/src/convert/fill.rs index 49c60a8..6c453b6 100644 --- a/src/convert/fill.rs +++ b/src/convert/fill.rs @@ -9,7 +9,7 @@ use svgdom::{ }; // self -use tree; +use tree::prelude::*; use short::{ AId, AValue, diff --git a/src/convert/gradient.rs b/src/convert/gradient.rs index 9d03b6e..e0acfe7 100644 --- a/src/convert/gradient.rs +++ b/src/convert/gradient.rs @@ -6,7 +6,7 @@ use svgdom; // self -use tree; +use tree::prelude::*; use short::{ AId, EId, @@ -23,7 +23,7 @@ pub fn convert_linear( let ref attrs = node.attributes(); let transform = attrs.get_transform(AId::GradientTransform).unwrap_or_default(); - let grad = rtree.append_defs( + let grad = rtree.append_to_defs( tree::NodeKind::LinearGradient(tree::LinearGradient { id: node.id().clone(), x1: attrs.get_number(AId::X1).unwrap_or(0.0), @@ -48,7 +48,7 @@ pub fn convert_radial( let ref attrs = node.attributes(); let transform = attrs.get_transform(AId::GradientTransform).unwrap_or_default(); - let grad = rtree.append_defs( + let grad = rtree.append_to_defs( tree::NodeKind::RadialGradient(tree::RadialGradient { id: node.id().clone(), cx: attrs.get_number(AId::Cx).unwrap_or(0.5), diff --git a/src/convert/image.rs b/src/convert/image.rs index 5f687b5..5963a10 100644 --- a/src/convert/image.rs +++ b/src/convert/image.rs @@ -9,7 +9,7 @@ use base64; use svgdom; // self -use tree; +use tree::prelude::*; use short::{ AId, }; diff --git a/src/convert/mod.rs b/src/convert/mod.rs index d31ad46..edf5140 100644 --- a/src/convert/mod.rs +++ b/src/convert/mod.rs @@ -9,7 +9,7 @@ use svgdom::{ }; // self -use tree; +use tree::prelude::*; use short::{ AId, AValue, @@ -58,7 +58,7 @@ pub fn convert_doc( view_box: get_view_box(&svg)?, }; - let mut rtree = tree::RenderTree::new(svg_kind); + let mut rtree = tree::RenderTree::create(svg_kind); convert_ref_nodes(svg_doc, opt, &mut rtree); convert_nodes(&svg, opt, rtree.root().id(), &mut rtree); diff --git a/src/convert/path.rs b/src/convert/path.rs index 0bfc02c..fdf15a7 100644 --- a/src/convert/path.rs +++ b/src/convert/path.rs @@ -10,7 +10,7 @@ use svgdom; use lyon_geom; // self -use tree; +use tree::prelude::*; use short::{ AId, }; diff --git a/src/convert/pattern.rs b/src/convert/pattern.rs index 03761a2..85c33ca 100644 --- a/src/convert/pattern.rs +++ b/src/convert/pattern.rs @@ -9,7 +9,7 @@ use svgdom::{ }; // self -use tree; +use tree::prelude::*; use short::{ AId, }; @@ -34,7 +34,7 @@ pub fn convert( debug_assert!(!rect.width().is_fuzzy_zero()); debug_assert!(!rect.height().is_fuzzy_zero()); - let patt_node = rtree.append_defs(tree::NodeKind::Pattern(tree::Pattern { + let patt_node = rtree.append_to_defs(tree::NodeKind::Pattern(tree::Pattern { id: node.id().clone(), units: super::convert_element_units(&attrs, AId::PatternUnits), content_units: super::convert_element_units(&attrs, AId::PatternContentUnits), diff --git a/src/convert/stroke.rs b/src/convert/stroke.rs index 815aca2..593e799 100644 --- a/src/convert/stroke.rs +++ b/src/convert/stroke.rs @@ -10,7 +10,7 @@ use svgdom::{ }; // self -use tree; +use tree::prelude::*; use short::{ AId, AValue, diff --git a/src/convert/text.rs b/src/convert/text.rs index 3d2df82..f34bc16 100644 --- a/src/convert/text.rs +++ b/src/convert/text.rs @@ -9,7 +9,7 @@ use svgdom::{ }; // self -use tree; +use tree::prelude::*; use short::{ AId, EId, @@ -97,7 +97,6 @@ pub trait Render { /// Renders SVG node to image. fn render_node_to_image( &self, - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, ) -> Result<Box<OutputImage>>; @@ -107,7 +106,6 @@ pub trait Render { /// Note: this method can be pretty expensive. fn calc_node_bbox( &self, - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, ) -> Option<Rect>; diff --git a/src/render_cairo/clippath.rs b/src/render_cairo/clippath.rs index e503e53..f30707c 100644 --- a/src/render_cairo/clippath.rs +++ b/src/render_cairo/clippath.rs @@ -28,7 +28,6 @@ use { pub fn apply( - rtree: &tree::RenderTree, node: tree::NodeRef, cp: &tree::ClipPath, opt: &Options, @@ -61,10 +60,10 @@ pub fn apply( match *node.value() { tree::NodeKind::Path(ref p) => { - path::draw(rtree, p, opt, &clip_cr); + path::draw(node.tree(), p, opt, &clip_cr); } tree::NodeKind::Text(_) => { - text::draw(rtree, node, opt, &clip_cr); + text::draw(node, opt, &clip_cr); } _ => {} } diff --git a/src/render_cairo/fill.rs b/src/render_cairo/fill.rs index bbfd2d3..f53063d 100644 --- a/src/render_cairo/fill.rs +++ b/src/render_cairo/fill.rs @@ -6,7 +6,10 @@ use cairo; // self -use tree; +use tree::{ + self, + TreeExt, +}; use math; use super::{ gradient, @@ -41,7 +44,7 @@ pub fn apply( gradient::prepare_radial(node, rg, fill.opacity, bbox, cr); } tree::NodeKind::Pattern(ref pattern) => { - pattern::apply(rtree, node, pattern, opt, bbox, cr); + pattern::apply(node, pattern, opt, bbox, cr); } _ => {} } diff --git a/src/render_cairo/mod.rs b/src/render_cairo/mod.rs index f8dd2d4..8191afa 100644 --- a/src/render_cairo/mod.rs +++ b/src/render_cairo/mod.rs @@ -16,6 +16,7 @@ use pangocairo::functions as pc; // self use tree::{ self, + TreeExt, NodeExt, }; use math::*; @@ -76,21 +77,19 @@ impl Render for Backend { fn render_node_to_image( &self, - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, ) -> Result<Box<OutputImage>> { - let img = render_node_to_image(rtree, node, opt)?; + let img = render_node_to_image(node, opt)?; Ok(Box::new(img)) } fn calc_node_bbox( &self, - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, ) -> Option<Rect> { - calc_node_bbox(rtree, node, opt) + calc_node_bbox(node, opt) } } @@ -134,11 +133,10 @@ pub fn render_to_image( /// Renders SVG to image. pub fn render_node_to_image( - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, ) -> Result<cairo::ImageSurface> { - let node_bbox = if let Some(bbox) = calc_node_bbox(rtree, node, opt) { + let node_bbox = if let Some(bbox) = calc_node_bbox(node, opt) { bbox } else { warn!("Node {:?} has zero size.", node.svg_id()); @@ -156,7 +154,7 @@ pub fn render_node_to_image( } apply_viewbox_transform(node_bbox, img_view, &cr); - render_node_to_canvas(rtree, node, opt, img_view.to_screen_size(), &cr); + render_node_to_canvas(node, opt, img_view.to_screen_size(), &cr); Ok(surface) } @@ -169,12 +167,11 @@ pub fn render_to_canvas( cr: &cairo::Context, ) { apply_viewbox_transform(rtree.svg_node().view_box, img_view, cr); - render_group(rtree, rtree.root(), opt, img_view.to_screen_size(), &cr); + render_group(rtree.root(), opt, img_view.to_screen_size(), &cr); } /// Renders SVG node to canvas. pub fn render_node_to_canvas( - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, img_size: ScreenSize, @@ -185,7 +182,7 @@ pub fn render_node_to_canvas( ts.append(&node.transform()); cr.transform(ts.to_native()); - render_node(rtree, node, opt, img_size, cr); + render_node(node, opt, img_size, cr); cr.set_matrix(curr_ts); } @@ -229,7 +226,6 @@ fn apply_viewbox_transform( } fn render_group( - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, img_size: ScreenSize, @@ -241,7 +237,7 @@ fn render_group( for node in node.children() { cr.transform(node.transform().to_native()); - let bbox = render_node(rtree, node, opt, img_size, cr); + let bbox = render_node(node, opt, img_size, cr); if let Some(bbox) = bbox { g_bbox.expand(bbox); @@ -254,7 +250,6 @@ fn render_group( } fn render_group_impl( - rtree: &tree::RenderTree, node: tree::NodeRef, g: &tree::Group, opt: &Options, @@ -278,12 +273,12 @@ fn render_group_impl( let sub_cr = cairo::Context::new(&sub_surface); sub_cr.set_matrix(cr.get_matrix()); - let bbox = render_group(rtree, node, opt, img_size, &sub_cr); + let bbox = render_group(node, opt, img_size, &sub_cr); if let Some(idx) = g.clip_path { - let clip_node = rtree.defs_at(idx); + let clip_node = node.tree().defs_at(idx); if let tree::NodeKind::ClipPath(ref cp) = *clip_node.value() { - clippath::apply(rtree, clip_node, cp, opt, bbox, img_size, &sub_cr); + clippath::apply(clip_node, cp, opt, bbox, img_size, &sub_cr); } } @@ -304,7 +299,6 @@ fn render_group_impl( } fn render_node( - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, img_size: ScreenSize, @@ -312,16 +306,16 @@ fn render_node( ) -> Option<Rect> { match *node.value() { tree::NodeKind::Path(ref path) => { - Some(path::draw(rtree, path, opt, cr)) + Some(path::draw(node.tree(), path, opt, cr)) } tree::NodeKind::Text(_) => { - Some(text::draw(rtree, node, opt, cr)) + Some(text::draw(node, opt, cr)) } tree::NodeKind::Image(ref img) => { Some(image::draw(img, cr)) } tree::NodeKind::Group(ref g) => { - render_group_impl(rtree, node, g, opt, img_size, cr) + render_group_impl(node, g, opt, img_size, cr) } _ => None, } @@ -331,28 +325,26 @@ fn render_node( /// /// Note: this method can be pretty expensive. pub fn calc_node_bbox( - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, ) -> Option<Rect> { // We can't use 1x1 image, like in Qt backend because otherwise // text layouts will be truncated. let (surface, img_view) = create_surface( - rtree.svg_node().size.to_screen_size(), + node.tree().svg_node().size.to_screen_size(), opt, ).unwrap(); let cr = cairo::Context::new(&surface); // We also have to apply the viewbox transform, // otherwise text hinting will be different and bbox will be different too. - apply_viewbox_transform(rtree.svg_node().view_box, img_view, &cr); + apply_viewbox_transform(node.tree().svg_node().view_box, img_view, &cr); let abs_ts = utils::abs_transform(node); - _calc_node_bbox(rtree, node, opt, abs_ts, &cr) + _calc_node_bbox(node, opt, abs_ts, &cr) } fn _calc_node_bbox( - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, ts: tree::Transform, @@ -394,7 +386,7 @@ fn _calc_node_bbox( let mut bbox = Rect::from_xywh(f64::MAX, f64::MAX, 0.0, 0.0); for child in node.children() { - if let Some(c_bbox) = _calc_node_bbox(rtree, child, opt, ts2, cr) { + if let Some(c_bbox) = _calc_node_bbox(child, opt, ts2, cr) { bbox.expand(c_bbox); } } diff --git a/src/render_cairo/pattern.rs b/src/render_cairo/pattern.rs index 0f1b68a..db05949 100644 --- a/src/render_cairo/pattern.rs +++ b/src/render_cairo/pattern.rs @@ -23,7 +23,6 @@ use { pub fn apply( - rtree: &tree::RenderTree, node: tree::NodeRef, pattern: &tree::Pattern, opt: &Options, @@ -66,7 +65,7 @@ pub fn apply( sub_cr.transform(cairo::Matrix::from_bbox(bbox)); } - super::render_group(rtree, node, opt, img_size, &sub_cr); + super::render_group(node, opt, img_size, &sub_cr); let mut ts = tree::Transform::default(); ts.append(&pattern.transform); diff --git a/src/render_cairo/stroke.rs b/src/render_cairo/stroke.rs index 6cde7e4..401e27f 100644 --- a/src/render_cairo/stroke.rs +++ b/src/render_cairo/stroke.rs @@ -6,7 +6,7 @@ use cairo; // self -use tree; +use tree::prelude::*; use math; use super::{ gradient, @@ -43,7 +43,7 @@ pub fn apply( gradient::prepare_radial(node, rg, stroke.opacity, bbox, cr); } tree::NodeKind::Pattern(ref pattern) => { - pattern::apply(rtree, node, pattern, opt, bbox, cr); + pattern::apply(node, pattern, opt, bbox, cr); } _ => {} } diff --git a/src/render_cairo/text.rs b/src/render_cairo/text.rs index 8c552ef..6e2d384 100644 --- a/src/render_cairo/text.rs +++ b/src/render_cairo/text.rs @@ -36,13 +36,12 @@ pub struct PangoData { } pub fn draw( - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, cr: &cairo::Context, ) -> Rect { draw_tspan(node, opt, cr, - |tspan, x, y, w, d| _draw_tspan(rtree, tspan, opt, x, y, w, d, cr)) + |tspan, x, y, w, d| _draw_tspan(node, tspan, opt, x, y, w, d, cr)) } pub fn draw_tspan<DrawAt>( @@ -108,7 +107,7 @@ pub fn draw_tspan<DrawAt>( } fn _draw_tspan( - rtree: &tree::RenderTree, + node: tree::NodeRef, tspan: &tree::TSpan, opt: &Options, x: f64, @@ -139,7 +138,7 @@ fn _draw_tspan( if let Some(ref style) = tspan.decoration.underline { line_rect.origin.y = y + baseline_offset - font_metrics.get_underline_position() as f64 / PANGO_SCALE_64; - draw_line(rtree, line_rect, &style.fill, &style.stroke, opt, cr); + draw_line(node.tree(), line_rect, &style.fill, &style.stroke, opt, cr); } // Draw overline. @@ -147,17 +146,17 @@ fn _draw_tspan( // Should be drawn before/under text. if let Some(ref style) = tspan.decoration.overline { line_rect.origin.y = y + font_metrics.get_underline_thickness() as f64 / PANGO_SCALE_64; - draw_line(rtree, line_rect, &style.fill, &style.stroke, opt, cr); + draw_line(node.tree(), line_rect, &style.fill, &style.stroke, opt, cr); } // Draw text. cr.move_to(x, y); - fill::apply(rtree, &tspan.fill, opt, bbox, cr); + fill::apply(node.tree(), &tspan.fill, opt, bbox, cr); pc::update_layout(cr, &pd.layout); pc::show_layout(cr, &pd.layout); - stroke::apply(rtree, &tspan.stroke, opt, bbox, cr); + stroke::apply(node.tree(), &tspan.stroke, opt, bbox, cr); pc::layout_path(cr, &pd.layout); cr.stroke(); @@ -170,7 +169,7 @@ fn _draw_tspan( line_rect.origin.y = y + baseline_offset - font_metrics.get_strikethrough_position() as f64 / PANGO_SCALE_64; line_rect.size.height = font_metrics.get_strikethrough_thickness() as f64 / PANGO_SCALE_64; - draw_line(rtree, line_rect, &style.fill, &style.stroke, opt, cr); + draw_line(node.tree(), line_rect, &style.fill, &style.stroke, opt, cr); } } diff --git a/src/render_qt/clippath.rs b/src/render_qt/clippath.rs index c962ed9..fcd394b 100644 --- a/src/render_qt/clippath.rs +++ b/src/render_qt/clippath.rs @@ -25,7 +25,6 @@ use { pub fn apply( - rtree: &tree::RenderTree, node: tree::NodeRef, cp: &tree::ClipPath, opt: &Options, @@ -57,10 +56,10 @@ pub fn apply( match *node.value() { tree::NodeKind::Path(ref path_node) => { - path::draw(rtree, path_node, opt, &clip_p); + path::draw(node.tree(), path_node, opt, &clip_p); } tree::NodeKind::Text(_) => { - text::draw(rtree, node, opt, &clip_p); + text::draw(node, opt, &clip_p); } _ => {} } diff --git a/src/render_qt/fill.rs b/src/render_qt/fill.rs index c96817a..494af28 100644 --- a/src/render_qt/fill.rs +++ b/src/render_qt/fill.rs @@ -6,7 +6,7 @@ use qt; // self -use tree; +use tree::prelude::*; use math::{ self, Rect, @@ -47,7 +47,7 @@ pub fn apply( } tree::NodeKind::Pattern(ref pattern) => { let ts = p.get_transform(); - pattern::apply(rtree, node, pattern, opt, ts, bbox, &mut brush); + pattern::apply(node, pattern, opt, ts, bbox, &mut brush); } _ => {} } diff --git a/src/render_qt/mod.rs b/src/render_qt/mod.rs index 238ddae..643b6e1 100644 --- a/src/render_qt/mod.rs +++ b/src/render_qt/mod.rs @@ -10,10 +10,7 @@ use std::f64; use qt; // self -use tree::{ - self, - NodeExt, -}; +use tree::prelude::*; use math::*; use traits::{ ConvTransform, @@ -71,17 +68,15 @@ impl Render for Backend { fn render_node_to_image( &self, - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, ) -> Result<Box<OutputImage>> { - let img = render_node_to_image(rtree, node, opt)?; + let img = render_node_to_image(node, opt)?; Ok(Box::new(img)) } fn calc_node_bbox( &self, - _: &tree::RenderTree, node: tree::NodeRef, opt: &Options, ) -> Option<Rect> { @@ -112,7 +107,6 @@ pub fn render_to_image( /// Renders SVG node to image. pub fn render_node_to_image( - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, ) -> Result<qt::Image> { @@ -127,7 +121,7 @@ pub fn render_node_to_image( let painter = qt::Painter::new(&img); apply_viewbox_transform(node_bbox, img_view, &painter); - render_node_to_canvas(rtree, node, opt, img_view, &painter); + render_node_to_canvas(node, opt, img_view, &painter); painter.end(); Ok(img) @@ -171,12 +165,11 @@ pub fn render_to_canvas( painter: &qt::Painter, ) { apply_viewbox_transform(rtree.svg_node().view_box, img_view, painter); - render_group(rtree, rtree.root(), opt, img_view.to_screen_size(), &painter); + render_group(rtree.root(), opt, img_view.to_screen_size(), &painter); } /// Renders SVG node to canvas. pub fn render_node_to_canvas( - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, img_view: Rect, @@ -187,7 +180,7 @@ pub fn render_node_to_canvas( ts.append(&node.transform()); painter.apply_transform(&ts.to_native()); - render_node(rtree, node, opt, img_view.to_screen_size(), painter); + render_node(node, opt, img_view.to_screen_size(), painter); painter.set_transform(&curr_ts); } @@ -207,7 +200,6 @@ pub fn apply_viewbox_transform( // TODO: render groups backward to reduce memory usage // current implementation keeps parent canvas until all children are rendered fn render_group( - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, img_size: ScreenSize, @@ -220,7 +212,7 @@ fn render_group( // Apply transform. p.apply_transform(&node.transform().to_native()); - let bbox = render_node(rtree, node, opt, img_size, p); + let bbox = render_node(node, opt, img_size, p); if let Some(bbox) = bbox { g_bbox.expand(bbox); @@ -234,7 +226,6 @@ fn render_group( } fn render_group_impl( - rtree: &tree::RenderTree, node: tree::NodeRef, g: &tree::Group, opt: &Options, @@ -259,12 +250,12 @@ fn render_group_impl( let sub_p = qt::Painter::new(&sub_img); sub_p.set_transform(&p.get_transform()); - let bbox = render_group(rtree, node, opt, img_size, &sub_p); + let bbox = render_group(node, opt, img_size, &sub_p); if let Some(idx) = g.clip_path { - let clip_node = rtree.defs_at(idx); + let clip_node = node.tree().defs_at(idx); if let tree::NodeKind::ClipPath(ref cp) = *clip_node.value() { - clippath::apply(rtree, clip_node, cp, opt, bbox, img_size, &sub_p); + clippath::apply(clip_node, cp, opt, bbox, img_size, &sub_p); } } @@ -286,7 +277,6 @@ fn render_group_impl( } fn render_node( - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, img_size: ScreenSize, @@ -294,16 +284,16 @@ fn render_node( ) -> Option<Rect> { match *node.value() { tree::NodeKind::Path(ref path) => { - Some(path::draw(rtree, path, opt, p)) + Some(path::draw(node.tree(), path, opt, p)) } tree::NodeKind::Text(_) => { - Some(text::draw(rtree, node, opt, p)) + Some(text::draw(node, opt, p)) } tree::NodeKind::Image(ref img) => { Some(image::draw(img, p)) } tree::NodeKind::Group(ref g) => { - render_group_impl(rtree, node, g, opt, img_size, p) + render_group_impl(node, g, opt, img_size, p) } _ => None, } diff --git a/src/render_qt/pattern.rs b/src/render_qt/pattern.rs index d0ff18d..3db3916 100644 --- a/src/render_qt/pattern.rs +++ b/src/render_qt/pattern.rs @@ -18,7 +18,6 @@ use { }; pub fn apply( - rtree: &tree::RenderTree, pattern_node: tree::NodeRef, pattern: &tree::Pattern, opt: &Options, @@ -61,7 +60,7 @@ pub fn apply( p.apply_transform(&qt::Transform::from_bbox(bbox)); } - super::render_group(rtree, pattern_node, opt, img_size, &p); + super::render_group(pattern_node, opt, img_size, &p); p.end(); brush.set_pattern(img); diff --git a/src/render_qt/stroke.rs b/src/render_qt/stroke.rs index 4b7fdff..bac8b86 100644 --- a/src/render_qt/stroke.rs +++ b/src/render_qt/stroke.rs @@ -6,7 +6,7 @@ use qt; // self -use tree; +use tree::prelude::*; use math::{ self, Rect, @@ -49,7 +49,7 @@ pub fn apply( } tree::NodeKind::Pattern(ref pattern) => { let ts = p.get_transform(); - pattern::apply(rtree, node, pattern, opt, ts, bbox, &mut brush); + pattern::apply(node, pattern, opt, ts, bbox, &mut brush); } _ => {} } diff --git a/src/render_qt/text.rs b/src/render_qt/text.rs index 2333115..99a7ac7 100644 --- a/src/render_qt/text.rs +++ b/src/render_qt/text.rs @@ -21,13 +21,12 @@ use { pub fn draw( - rtree: &tree::RenderTree, node: tree::NodeRef, opt: &Options, p: &qt::Painter, ) -> Rect { draw_tspan(node, p, - |tspan, x, y, w, font| _draw_tspan(rtree, tspan, opt, x, y, w, &font, p)) + |tspan, x, y, w, font| _draw_tspan(node, tspan, opt, x, y, w, &font, p)) } pub fn draw_tspan<DrawAt>( @@ -80,7 +79,7 @@ pub fn draw_tspan<DrawAt>( } fn _draw_tspan( - rtree: &tree::RenderTree, + node: tree::NodeRef, tspan: &tree::TSpan, opt: &Options, x: f64, @@ -107,7 +106,7 @@ fn _draw_tspan( // Should be drawn before/under text. if let Some(ref style) = tspan.decoration.underline { line_rect.origin.y = y + font_metrics.height() - font_metrics.underline_pos(); - draw_line(rtree, line_rect, &style.fill, &style.stroke, opt, p); + draw_line(node.tree(), line_rect, &style.fill, &style.stroke, opt, p); } // Draw overline. @@ -115,14 +114,14 @@ fn _draw_tspan( // Should be drawn before/under text. if let Some(ref style) = tspan.decoration.overline { line_rect.origin.y = y + font_metrics.height() - font_metrics.overline_pos(); - draw_line(rtree, line_rect, &style.fill, &style.stroke, opt, p); + draw_line(node.tree(), line_rect, &style.fill, &style.stroke, opt, p); } let bbox = Rect::from_xywh(0.0, 0.0, width, font_metrics.height()); // Draw text. - fill::apply(rtree, &tspan.fill, opt, bbox, p); - stroke::apply(rtree, &tspan.stroke, opt, bbox, p); + fill::apply(node.tree(), &tspan.fill, opt, bbox, p); + stroke::apply(node.tree(), &tspan.stroke, opt, bbox, p); p.draw_text(x, y, &tspan.text); @@ -131,7 +130,7 @@ fn _draw_tspan( // Should be drawn after/over text. if let Some(ref style) = tspan.decoration.line_through { line_rect.origin.y = y + baseline_offset - font_metrics.strikeout_pos(); - draw_line(rtree, line_rect, &style.fill, &style.stroke, opt, p); + draw_line(node.tree(), line_rect, &style.fill, &style.stroke, opt, p); } } diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 0808cb4..d47bbca 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -16,6 +16,12 @@ mod attribute; mod dump; mod node; +/// Basic modules and traits for tree manipulation. +pub mod prelude { + pub use tree; + pub use super::NodeExt; + pub use super::TreeExt; +} /// Alias for ego_tree::NodeId<NodeKind>. pub type NodeId = ego_tree::NodeId<NodeKind>; @@ -29,28 +35,50 @@ pub type NodeMut<'a> = ego_tree::NodeMut<'a, NodeKind>; /// A rendering tree container. /// /// Contains all the nodes that are required for rendering. -pub struct RenderTree(ego_tree::Tree<NodeKind>); +/// +/// Alias for ego_tree::Tree<NodeKind>. +pub type RenderTree = ego_tree::Tree<NodeKind>; -impl RenderTree { +/// Additional `RenderTree` methods. +pub trait TreeExt { /// Creates a new `RenderTree`. - pub fn new(svg: Svg) -> Self { - let mut tree = ego_tree::Tree::new(NodeKind::Svg(svg)); - tree.root_mut().append(NodeKind::Defs); - RenderTree(tree) - } + fn create(svg: Svg) -> Self; - /// Returns the root node. - pub fn root(&self) -> NodeRef { - self.0.root() - } + /// Returns the `Svg` node's data. + fn svg_node(&self) -> &Svg; + + /// Returns the `Defs` node. + fn defs(&self) -> NodeRef; + + /// Checks that `node` is part of the `Defs` children. + fn is_in_defs(&self, node: NodeRef) -> bool; + + /// Appends `NodeKind` to the `Defs` node. + fn append_to_defs(&mut self, kind: NodeKind) -> NodeId; + + /// Append `NodeKind` as a child to the node by `NodeId`. + fn append_child(&mut self, parent: NodeId, kind: NodeKind) -> NodeId; + + /// Returns `Defs` node child by `NodeId`. + fn defs_at(&self, id: NodeId) -> NodeRef; + + /// Searches for `NodeId` in `Defs` children by ID. + fn defs_id(&self, id: &str) -> Option<NodeId>; + + /// Converts the document to `svgdom::Document`. + /// + /// Used to save document to file for debug purposes. + fn to_svgdom(&self) -> svgdom::Document; +} - /// Returns the mutable root node. - pub fn root_mut(&mut self) -> NodeMut { - self.0.root_mut() +impl TreeExt for RenderTree { + fn create(svg: Svg) -> Self { + let mut tree = ego_tree::Tree::new(NodeKind::Svg(svg)); + tree.root_mut().append(NodeKind::Defs); + tree } - /// Returns the `Svg` node's data. - pub fn svg_node(&self) -> &Svg { + fn svg_node(&self) -> &Svg { if let NodeKind::Svg(ref svg) = *self.root().value() { svg } else { @@ -58,28 +86,26 @@ impl RenderTree { } } - /// Returns the `Defs` node. - pub fn defs(&self) -> NodeRef { + fn defs(&self) -> NodeRef { self.root().first_child().unwrap() } - /// Checks that `node` is part of the `Defs` children. - pub fn is_in_defs(&self, node: NodeRef) -> bool { + fn is_in_defs(&self, node: NodeRef) -> bool { let defs = self.defs(); node.ancestors().find(|n| *n == defs).is_some() } - pub(crate) fn append_defs(&mut self, kind: NodeKind) -> NodeId { + fn append_to_defs(&mut self, kind: NodeKind) -> NodeId { let defs_id = self.defs().id(); self.append_child(defs_id, kind) } - pub(crate) fn append_child(&mut self, parent: NodeId, kind: NodeKind) -> NodeId { - let mut parent = self.0.get_mut(parent); + fn append_child(&mut self, parent: NodeId, kind: NodeKind) -> NodeId { + let mut parent = self.get_mut(parent); parent.append(kind).id() } - pub(crate) fn defs_at(&self, id: NodeId) -> NodeRef { + fn defs_at(&self, id: NodeId) -> NodeRef { for n in self.defs().children() { if n.id() == id { return n; @@ -89,7 +115,7 @@ impl RenderTree { unreachable!(); } - pub(crate) fn defs_id(&self, id: &str) -> Option<NodeId> { + fn defs_id(&self, id: &str) -> Option<NodeId> { for n in self.defs().children() { if n.svg_id() == id { return Some(n.id()); @@ -99,15 +125,12 @@ impl RenderTree { unreachable!(); } - /// Converts the document to `svgdom::Document`. - /// - /// Used to save document to file for debug purposes. - pub fn to_svgdom(&self) -> svgdom::Document { + fn to_svgdom(&self) -> svgdom::Document { dump::conv_doc(self) } } -/// Additional `NodeRef` method. +/// Additional `NodeRef` methods. pub trait NodeExt { /// Returns node's ID. /// @@ -120,9 +143,6 @@ pub trait NodeExt { /// If a current node doesn't support transformation - a default /// transform will be returned. fn transform(&self) -> Transform; - - /// Returns an iterator over this node and its descendants. - fn descendants(&self) -> Descendants; } impl<'a> NodeExt for NodeRef<'a> { @@ -133,25 +153,4 @@ impl<'a> NodeExt for NodeRef<'a> { fn transform(&self) -> Transform { self.value().transform() } - - fn descendants(&self) -> Descendants { - Descendants(self.traverse()) - } -} - -/// Iterator over node and its descendants. -pub struct Descendants<'a>(ego_tree::iter::Traverse<'a, NodeKind>); - -impl<'a> Iterator for Descendants<'a> { - type Item = NodeRef<'a>; - - fn next(&mut self) -> Option<NodeRef<'a>> { - loop { - match self.0.next() { - Some(ego_tree::iter::Edge::Open(node)) => return Some(node), - Some(ego_tree::iter::Edge::Close(_)) => {} - None => return None - } - } - } } diff --git a/tools/rendersvg/src/main.rs b/tools/rendersvg/src/main.rs index 728c4bf..5d3483c 100644 --- a/tools/rendersvg/src/main.rs +++ b/tools/rendersvg/src/main.rs @@ -29,13 +29,13 @@ use clap::{ }; use resvg::{ - tree, FitTo, Options, NodeExt, RectExt, Render, }; +use resvg::tree::prelude::*; use svgdom::{ ChainedErrorExt, @@ -125,7 +125,7 @@ fn process() -> Result<(), Error> { if let Some(ref out_png) = args.out_png { let img = if let Some(ref id) = args.export_id { if let Some(node) = rtree.root().descendants().find(|n| n.svg_id() == id) { - args.backend.render_node_to_image(&rtree, node, &opt) + args.backend.render_node_to_image(node, &opt) } else { return Err(Error::InvalidId(id.clone())); } @@ -186,7 +186,7 @@ fn query_all( (v * 1000.0).round() / 1000.0 } - if let Some(bbox) = args.backend.calc_node_bbox(&rtree, node, &opt) { + if let Some(bbox) = args.backend.calc_node_bbox(node, &opt) { println!("{},{},{},{},{}", node.svg_id(), round_len(bbox.x()), round_len(bbox.y()), round_len(bbox.width()), round_len(bbox.height())); |