[librsvg] NodeUse: release the acquired child as soon as possible
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] NodeUse: release the acquired child as soon as possible
- Date: Wed, 19 Sep 2018 16:42:45 +0000 (UTC)
commit cf2da5828ff1abd323e4592fb5ea360ad415eb30
Author: Federico Mena Quintero <federico gnome org>
Date: Wed Sep 19 11:23:35 2018 -0500
NodeUse: release the acquired child as soon as possible
This is so that the child's drawing method will be able to re-acquire
the child for other purposes.
rsvg_internals/src/structure.rs | 155 ++++++++++++++++++++--------------------
1 file changed, 79 insertions(+), 76 deletions(-)
---
diff --git a/rsvg_internals/src/structure.rs b/rsvg_internals/src/structure.rs
index 5fd36201..030293b5 100644
--- a/rsvg_internals/src/structure.rs
+++ b/rsvg_internals/src/structure.rs
@@ -293,86 +293,89 @@ impl NodeTrait for NodeUse {
return Ok(());
}
- if let Some(acquired) = draw_ctx.get_acquired_node(link.as_ref().unwrap()) {
- let child = acquired.get();
+ let child = if let Some(acquired) = draw_ctx.get_acquired_node(link.as_ref().unwrap()) {
+ // Here we clone the acquired child, so that we can drop the AcquiredNode as
+ // early as possible. This is so that the child's drawing method will be able
+ // to re-acquire the child for other purposes.
+ acquired.get().clone()
+ } else {
+ return Ok(());
+ };
- if Node::is_ancestor(node.clone(), child.clone()) {
- // or, if we're <use>'ing ourselves
- return Err(RenderingError::CircularReference);
- }
+ if Node::is_ancestor(node.clone(), child.clone()) {
+ // or, if we're <use>'ing ourselves
+ return Err(RenderingError::CircularReference);
+ }
- draw_ctx.increase_num_elements_rendered_through_use(1);
-
- let params = draw_ctx.get_view_params();
-
- let nx = self.x.get().normalize(values, ¶ms);
- let ny = self.y.get().normalize(values, ¶ms);
-
- // If attributes ‘width’ and/or ‘height’ are not specified,
- // [...] use values of '100%' for these attributes.
- // From https://www.w3.org/TR/SVG/struct.html#UseElement in
- // "If the ‘use’ element references a ‘symbol’ element"
-
- let nw = self
- .w
- .get()
- .unwrap_or_else(|| Length::parse_str("100%", LengthDir::Horizontal).unwrap())
- .normalize(values, ¶ms);
- let nh = self
- .h
- .get()
- .unwrap_or_else(|| Length::parse_str("100%", LengthDir::Vertical).unwrap())
- .normalize(values, ¶ms);
-
- // width or height set to 0 disables rendering of the element
- // https://www.w3.org/TR/SVG/struct.html#UseElementWidthAttribute
- if nw.approx_eq_cairo(&0.0) || nh.approx_eq_cairo(&0.0) {
- return Ok(());
- }
+ draw_ctx.increase_num_elements_rendered_through_use(1);
- if child.get_type() != NodeType::Symbol {
- let cr = draw_ctx.get_cairo_context();
- cr.translate(nx, ny);
-
- draw_ctx.with_discrete_layer(node, values, clipping, &mut |dc| {
- dc.draw_node_from_stack(
- &CascadedValues::new_from_values(&child, values),
- &child,
- clipping,
- )
- })
- } else {
- child.with_impl(|symbol: &NodeSymbol| {
- let do_clip = !values.is_overflow()
- || (values.overflow == Overflow::Visible && child.is_overflow());
-
- draw_in_viewport(
- nx,
- ny,
- nw,
- nh,
- ClipMode::ClipToVbox,
- do_clip,
- symbol.vbox.get(),
- symbol.preserve_aspect_ratio.get(),
- node,
- values,
- draw_ctx.get_cairo_context().get_matrix(),
- draw_ctx,
- clipping,
- &mut |dc| {
- // We don't push a layer because draw_in_viewport() already does it
- child.draw_children(
- &CascadedValues::new_from_values(&child, values),
- dc,
- clipping,
- )
- },
- )
- })
- }
+ let params = draw_ctx.get_view_params();
+
+ let nx = self.x.get().normalize(values, ¶ms);
+ let ny = self.y.get().normalize(values, ¶ms);
+
+ // If attributes ‘width’ and/or ‘height’ are not specified,
+ // [...] use values of '100%' for these attributes.
+ // From https://www.w3.org/TR/SVG/struct.html#UseElement in
+ // "If the ‘use’ element references a ‘symbol’ element"
+
+ let nw = self
+ .w
+ .get()
+ .unwrap_or_else(|| Length::parse_str("100%", LengthDir::Horizontal).unwrap())
+ .normalize(values, ¶ms);
+ let nh = self
+ .h
+ .get()
+ .unwrap_or_else(|| Length::parse_str("100%", LengthDir::Vertical).unwrap())
+ .normalize(values, ¶ms);
+
+ // width or height set to 0 disables rendering of the element
+ // https://www.w3.org/TR/SVG/struct.html#UseElementWidthAttribute
+ if nw.approx_eq_cairo(&0.0) || nh.approx_eq_cairo(&0.0) {
+ return Ok(());
+ }
+
+ if child.get_type() != NodeType::Symbol {
+ let cr = draw_ctx.get_cairo_context();
+ cr.translate(nx, ny);
+
+ draw_ctx.with_discrete_layer(node, values, clipping, &mut |dc| {
+ dc.draw_node_from_stack(
+ &CascadedValues::new_from_values(&child, values),
+ &child,
+ clipping,
+ )
+ })
} else {
- Ok(())
+ child.with_impl(|symbol: &NodeSymbol| {
+ let do_clip = !values.is_overflow()
+ || (values.overflow == Overflow::Visible && child.is_overflow());
+
+ draw_in_viewport(
+ nx,
+ ny,
+ nw,
+ nh,
+ ClipMode::ClipToVbox,
+ do_clip,
+ symbol.vbox.get(),
+ symbol.preserve_aspect_ratio.get(),
+ node,
+ values,
+ draw_ctx.get_cairo_context().get_matrix(),
+ draw_ctx,
+ clipping,
+ &mut |dc| {
+ // We don't push a layer because draw_in_viewport() already does it
+ child.draw_children(
+ &CascadedValues::new_from_values(&child, values),
+ dc,
+ clipping,
+ )
+ },
+ )
+ })
}
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]