[librsvg: 5/7] Turn NodeData into an enum with variants for Element and Text
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 5/7] Turn NodeData into an enum with variants for Element and Text
- Date: Fri, 13 Mar 2020 01:58:14 +0000 (UTC)
commit 741a0c0bb4c9bc5dc4b246a92d9ba2e26275d45d
Author: Federico Mena Quintero <federico gnome org>
Date: Thu Mar 12 15:19:29 2020 -0600
Turn NodeData into an enum with variants for Element and Text
pub enum NodeData {
Element(Element),
Text(NodeChars),
}
The old NodeData is now Element.
This will let us box the Element, so that it takes as little space as
possible for the enum when it has a NodeData::Text value.
To make this easier for the rest of the code, now there is a
NodeBorrow trait, implemented for RsvgNode and imported pretty much
everywhere, with the following methods:
pub trait NodeBorrow {
/// Returns `false` for NodeData::Text, `true` otherwise.
fn is_element(&self) -> bool;
/// Borrows a `NodeChars` reference.
///
/// Panics: will panic if `&self` is not a `NodeData::Text` node
fn borrow_chars(&self) -> Ref<NodeChars>;
/// Borrows an `Element` reference
///
/// Panics: will panic if `&self` is not a `NodeData::Element` node
fn borrow_element(&self) -> Ref<Element>;
/// Borrows an `Element` reference mutably
///
/// Panics: will panic if `&self` is not a `NodeData::Element` node
fn borrow_element_mut(&mut self) -> RefMut<Element>;
}
So, instead of doing node.borrow() -> Ref<NodeData>, we now can do
node.borrow_element() directly, for example.
The calling code is still supposed to first ensure that a node
is_element() or not, just like it was doing
`get_type() == NodeType::Foo` before doing get_impl::<Foo>().
rsvg_internals/src/css.rs | 22 +--
rsvg_internals/src/document.rs | 19 +--
rsvg_internals/src/drawing_ctx.rs | 31 ++--
rsvg_internals/src/filters/component_transfer.rs | 26 ++--
rsvg_internals/src/filters/context.rs | 10 +-
rsvg_internals/src/filters/light/lighting.rs | 19 ++-
rsvg_internals/src/filters/merge.rs | 10 +-
rsvg_internals/src/filters/mod.rs | 27 ++--
rsvg_internals/src/gradient.rs | 12 +-
rsvg_internals/src/handle.rs | 8 +-
rsvg_internals/src/marker.rs | 2 +-
rsvg_internals/src/node.rs | 175 ++++++++++++++++-------
rsvg_internals/src/pattern.rs | 9 +-
rsvg_internals/src/structure.rs | 4 +-
rsvg_internals/src/text.rs | 19 +--
rsvg_internals/src/xml.rs | 12 +-
16 files changed, 248 insertions(+), 157 deletions(-)
---
diff --git a/rsvg_internals/src/css.rs b/rsvg_internals/src/css.rs
index dcc7d81f..8bd635b7 100644
--- a/rsvg_internals/src/css.rs
+++ b/rsvg_internals/src/css.rs
@@ -92,7 +92,7 @@ use url::Url;
use crate::allowed_url::AllowedUrl;
use crate::error::*;
use crate::io::{self, BinaryData};
-use crate::node::{NodeCascade, NodeType, RsvgNode};
+use crate::node::{NodeBorrow, NodeCascade, NodeType, RsvgNode};
use crate::properties::{parse_property, ComputedValues, ParsedProperty};
/// A parsed CSS declaration
@@ -450,17 +450,17 @@ impl selectors::Element for RsvgElement {
}
fn has_local_name(&self, local_name: &LocalName) -> bool {
- self.0.borrow().element_name().local == *local_name
+ self.0.borrow_element().element_name().local == *local_name
}
/// Empty string for no namespace
fn has_namespace(&self, ns: &Namespace) -> bool {
- self.0.borrow().element_name().ns == *ns
+ self.0.borrow_element().element_name().ns == *ns
}
/// Whether this element and the `other` element have the same local name and namespace.
fn is_same_type(&self, other: &Self) -> bool {
- self.0.borrow().element_name() == other.0.borrow().element_name()
+ self.0.borrow_element().element_name() == other.0.borrow_element().element_name()
}
fn attr_matches(
@@ -508,7 +508,7 @@ impl selectors::Element for RsvgElement {
fn has_id(&self, id: &LocalName, case_sensitivity: CaseSensitivity) -> bool {
self.0
- .borrow()
+ .borrow_element()
.get_id()
.map(|self_id| case_sensitivity.eq(self_id.as_bytes(), id.as_ref().as_bytes()))
.unwrap_or(false)
@@ -516,7 +516,7 @@ impl selectors::Element for RsvgElement {
fn has_class(&self, name: &LocalName, case_sensitivity: CaseSensitivity) -> bool {
self.0
- .borrow()
+ .borrow_element()
.get_class()
.map(|classes| {
classes
@@ -548,8 +548,7 @@ impl selectors::Element for RsvgElement {
fn is_empty(&self) -> bool {
!self.0.has_children()
|| self.0.children().all(|child| {
- child.borrow().get_type() == NodeType::Chars
- && child.borrow().get_chars().is_empty()
+ child.borrow().get_type() == NodeType::Chars && child.borrow_chars().is_empty()
})
}
@@ -736,7 +735,7 @@ impl Stylesheet {
/// Runs the CSS cascade on the specified tree from all the stylesheets
pub fn cascade(root: &mut RsvgNode, stylesheets: &[Stylesheet], extra: &[Stylesheet]) {
- for mut node in root.descendants() {
+ for mut node in root.descendants().filter(|n| n.is_element()) {
let mut matches = Vec::new();
let mut match_ctx = MatchingContext::new(
@@ -755,10 +754,11 @@ pub fn cascade(root: &mut RsvgNode, stylesheets: &[Stylesheet], extra: &[Stylesh
matches.as_mut_slice().sort();
for m in matches {
- node.borrow_mut().apply_style_declaration(m.declaration);
+ node.borrow_element_mut()
+ .apply_style_declaration(m.declaration);
}
- node.borrow_mut().set_style_attribute();
+ node.borrow_element_mut().set_style_attribute();
}
let values = ComputedValues::default();
diff --git a/rsvg_internals/src/document.rs b/rsvg_internals/src/document.rs
index 06db47b3..46d94a98 100644
--- a/rsvg_internals/src/document.rs
+++ b/rsvg_internals/src/document.rs
@@ -14,7 +14,7 @@ use crate::error::{AcquireError, LoadingError};
use crate::handle::LoadOptions;
use crate::io::{self, BinaryData};
use crate::limits;
-use crate::node::{NodeData, NodeType, RsvgNode};
+use crate::node::{NodeBorrow, NodeData, NodeType, RsvgNode};
use crate::property_bag::PropertyBag;
use crate::structure::{IntrinsicDimensions, Svg};
use crate::surface_utils::shared_surface::SharedImageSurface;
@@ -95,10 +95,10 @@ impl Document {
/// Gets the dimension parameters of the toplevel `<svg>`.
pub fn get_intrinsic_dimensions(&self) -> IntrinsicDimensions {
let root = self.root();
- let node_data = root.borrow();
+ let elt = root.borrow_element();
- assert!(node_data.get_type() == NodeType::Svg);
- node_data.get_impl::<Svg>().get_intrinsic_dimensions()
+ assert!(elt.get_type() == NodeType::Svg);
+ elt.get_impl::<Svg>().get_intrinsic_dimensions()
}
/// Runs the CSS cascade on the document tree
@@ -434,15 +434,18 @@ impl DocumentBuilder {
) -> RsvgNode {
let mut node = create_node(name, pbag);
- if let Some(id) = node.borrow().get_id() {
+ if let Some(id) = node.borrow_element().get_id() {
// This is so we don't overwrite an existing id
self.ids
.entry(id.to_string())
.or_insert_with(|| node.clone());
}
- node.borrow_mut()
- .set_atts(parent.as_ref().clone(), pbag, self.load_options.locale());
+ node.borrow_element_mut().set_atts(
+ parent.as_ref().clone(),
+ pbag,
+ self.load_options.locale(),
+ );
if let Some(mut parent) = parent {
parent.append(node.clone());
@@ -484,7 +487,7 @@ impl DocumentBuilder {
child
};
- chars_node.borrow().get_chars().append(text);
+ chars_node.borrow_chars().append(text);
}
pub fn resolve_href(&self, href: &str) -> Result<AllowedUrl, AllowedUrlError> {
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index afa33959..7a5c60e2 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -18,7 +18,7 @@ use crate::error::{AcquireError, RenderingError};
use crate::filters;
use crate::gradient::{LinearGradient, RadialGradient};
use crate::marker;
-use crate::node::{CascadedValues, NodeDraw, NodeType, RsvgNode};
+use crate::node::{CascadedValues, NodeBorrow, NodeDraw, NodeType, RsvgNode};
use crate::paint_server::{PaintServer, PaintSource};
use crate::path_builder::*;
use crate::pattern::Pattern;
@@ -318,7 +318,7 @@ impl DrawingCtx {
bbox: &BoundingBox,
) -> Result<(), RenderingError> {
if let Some(node) = clip_node {
- let units = node.borrow().get_impl::<ClipPath>().get_units();
+ let units = node.borrow_element().get_impl::<ClipPath>().get_units();
if units == CoordUnits::ObjectBoundingBox && bbox.rect.is_none() {
// The node being clipped is empty / doesn't have a
@@ -397,7 +397,7 @@ impl DrawingCtx {
};
let mask_transform = mask_node
- .borrow()
+ .borrow_element()
.get_transform()
.post_transform(&transform);
@@ -576,7 +576,7 @@ impl DrawingCtx {
res = res.and_then(|bbox| {
dc.generate_cairo_mask(
- &mask_node.borrow().get_impl::<Mask>(),
+ &mask_node.borrow_element().get_impl::<Mask>(),
&mask_node,
affines.for_temporary_surface,
&bbox,
@@ -742,7 +742,7 @@ impl DrawingCtx {
Ok(acquired) => {
let filter_node = acquired.get();
- if !filter_node.borrow().is_in_error() {
+ if !filter_node.borrow_element().is_in_error() {
// FIXME: deal with out of memory here
filters::render(
&filter_node,
@@ -816,7 +816,7 @@ impl DrawingCtx {
had_paint_server = match node.borrow().get_type() {
NodeType::LinearGradient => node
- .borrow()
+ .borrow_element()
.get_impl::<LinearGradient>()
.resolve_fallbacks_and_set_pattern(
&node,
@@ -826,7 +826,7 @@ impl DrawingCtx {
bbox,
)?,
NodeType::RadialGradient => node
- .borrow()
+ .borrow_element()
.get_impl::<RadialGradient>()
.resolve_fallbacks_and_set_pattern(
&node,
@@ -836,7 +836,7 @@ impl DrawingCtx {
bbox,
)?,
NodeType::Pattern => node
- .borrow()
+ .borrow_element()
.get_impl::<Pattern>()
.resolve_fallbacks_and_set_pattern(
&node,
@@ -1112,8 +1112,8 @@ impl DrawingCtx {
cascaded: &CascadedValues<'_>,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
- let node_data = node.borrow();
- let use_ = node_data.get_impl::<Use>();
+ let elt = node.borrow_element();
+ let use_ = elt.get_impl::<Use>();
// <use> is an element that is used directly, unlike
// <pattern>, which is used through a fill="url(#...)"
@@ -1181,11 +1181,11 @@ impl DrawingCtx {
)
})
} else {
- let node_data = child.borrow();
- let symbol = node_data.get_impl::<Symbol>();
+ let elt = child.borrow_element();
+ let symbol = elt.get_impl::<Symbol>();
let clip_mode = if !values.is_overflow()
- || (values.overflow == Overflow::Visible && child.borrow().is_overflow())
+ || (values.overflow == Overflow::Visible && child.borrow_element().is_overflow())
{
Some(ClipMode::ClipToVbox)
} else {
@@ -1270,7 +1270,10 @@ fn get_clip_in_user_and_object_space(
.and_then(|acquired| {
let clip_node = acquired.get().clone();
- let units = clip_node.borrow().get_impl::<ClipPath>().get_units();
+ let units = clip_node
+ .borrow_element()
+ .get_impl::<ClipPath>()
+ .get_units();
match units {
CoordUnits::UserSpaceOnUse => Some((Some(clip_node), None)),
diff --git a/rsvg_internals/src/filters/component_transfer.rs
b/rsvg_internals/src/filters/component_transfer.rs
index 91af86f1..89907746 100644
--- a/rsvg_internals/src/filters/component_transfer.rs
+++ b/rsvg_internals/src/filters/component_transfer.rs
@@ -6,7 +6,7 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::error::*;
-use crate::node::{NodeResult, NodeTrait, NodeType, RsvgNode};
+use crate::node::{NodeBorrow, NodeResult, NodeTrait, NodeType, RsvgNode};
use crate::number_list::{NumberList, NumberListLength};
use crate::parsers::{Parse, ParseValue};
use crate::property_bag::PropertyBag;
@@ -257,7 +257,7 @@ macro_rules! func_or_default {
($func_node:ident, $func_type:ty, $func_data:ident, $func_default:ident) => {
match $func_node {
Some(ref f) => {
- $func_data = f.borrow();
+ $func_data = f.borrow_element();
$func_data.get_impl::<$func_type>()
}
_ => &$func_default,
@@ -295,7 +295,7 @@ impl FilterEffect for FeComponentTransfer {
node.children()
.rev()
.filter(|c| c.borrow().get_type() == node_type)
- .find(|c| c.borrow().get_impl::<F>().channel() == channel)
+ .find(|c| c.borrow_element().get_impl::<F>().channel() == channel)
};
let func_r_node = get_node::<FeFuncR>(node, NodeType::FeFuncR, Channel::R);
@@ -307,7 +307,7 @@ impl FilterEffect for FeComponentTransfer {
.iter()
.filter_map(|x| x.as_ref())
{
- if node.borrow().is_in_error() {
+ if node.borrow_element().is_in_error() {
return Err(FilterError::ChildNodeInError);
}
}
@@ -319,15 +319,15 @@ impl FilterEffect for FeComponentTransfer {
let func_a_default = FeFuncA::default();
// We need to tell the borrow checker that these live long enough
- let func_r_data;
- let func_g_data;
- let func_b_data;
- let func_a_data;
-
- let func_r = func_or_default!(func_r_node, FeFuncR, func_r_data, func_r_default);
- let func_g = func_or_default!(func_g_node, FeFuncG, func_g_data, func_g_default);
- let func_b = func_or_default!(func_b_node, FeFuncB, func_b_data, func_b_default);
- let func_a = func_or_default!(func_a_node, FeFuncA, func_a_data, func_a_default);
+ let func_r_element;
+ let func_g_element;
+ let func_b_element;
+ let func_a_element;
+
+ let func_r = func_or_default!(func_r_node, FeFuncR, func_r_element, func_r_default);
+ let func_g = func_or_default!(func_g_node, FeFuncG, func_g_element, func_g_default);
+ let func_b = func_or_default!(func_b_node, FeFuncB, func_b_element, func_b_default);
+ let func_a = func_or_default!(func_a_node, FeFuncA, func_a_element, func_a_default);
#[inline]
fn compute_func<'a, F>(func: &'a F) -> impl Fn(u8, f64, f64) -> u8 + 'a
diff --git a/rsvg_internals/src/filters/context.rs b/rsvg_internals/src/filters/context.rs
index 9a1556e0..5d2f748b 100644
--- a/rsvg_internals/src/filters/context.rs
+++ b/rsvg_internals/src/filters/context.rs
@@ -7,7 +7,7 @@ use crate::coord_units::CoordUnits;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::{DrawingCtx, ViewParams};
use crate::filter::Filter;
-use crate::node::RsvgNode;
+use crate::node::{NodeBorrow, RsvgNode};
use crate::paint_server::PaintServer;
use crate::properties::ComputedValues;
use crate::rect::IRect;
@@ -111,8 +111,8 @@ impl FilterContext {
// However, with userSpaceOnUse it's still possible to create images with a filter.
let bbox_rect = node_bbox.rect.unwrap_or_default();
- let node_data = filter_node.borrow();
- let filter = node_data.get_impl::<Filter>();
+ let elt = filter_node.borrow_element();
+ let filter = elt.get_impl::<Filter>();
let affine = match filter.get_filter_units() {
CoordUnits::UserSpaceOnUse => draw_transform,
@@ -256,8 +256,8 @@ impl FilterContext {
/// Pushes the viewport size based on the value of `primitiveUnits`.
pub fn get_view_params(&self, draw_ctx: &mut DrawingCtx) -> ViewParams {
- let node_data = self.node.borrow();
- let filter = node_data.get_impl::<Filter>();
+ let elt = self.node.borrow_element();
+ let filter = elt.get_impl::<Filter>();
// See comments in compute_effects_region() for how this works.
if filter.get_primitive_units() == CoordUnits::ObjectBoundingBox {
diff --git a/rsvg_internals/src/filters/light/lighting.rs b/rsvg_internals/src/filters/light/lighting.rs
index 020411cd..01b41a3e 100644
--- a/rsvg_internals/src/filters/light/lighting.rs
+++ b/rsvg_internals/src/filters/light/lighting.rs
@@ -18,7 +18,7 @@ use crate::filters::{
},
FilterEffect, FilterError, PrimitiveWithInput,
};
-use crate::node::{CascadedValues, NodeResult, NodeTrait, NodeType, RsvgNode};
+use crate::node::{CascadedValues, NodeBorrow, NodeResult, NodeTrait, NodeType, RsvgNode};
use crate::parsers::{NumberOptionalNumber, ParseValue};
use crate::property_bag::PropertyBag;
use crate::surface_utils::{
@@ -504,14 +504,23 @@ fn find_light_source(node: &RsvgNode, ctx: &FilterContext) -> Result<LightSource
}
let node = node.unwrap();
- if node.borrow().is_in_error() {
+ if node.borrow_element().is_in_error() {
return Err(FilterError::ChildNodeInError);
}
let light_source = match node.borrow().get_type() {
- NodeType::FeDistantLight => node.borrow().get_impl::<FeDistantLight>().transform(ctx),
- NodeType::FePointLight => node.borrow().get_impl::<FePointLight>().transform(ctx),
- NodeType::FeSpotLight => node.borrow().get_impl::<FeSpotLight>().transform(ctx),
+ NodeType::FeDistantLight => node
+ .borrow_element()
+ .get_impl::<FeDistantLight>()
+ .transform(ctx),
+ NodeType::FePointLight => node
+ .borrow_element()
+ .get_impl::<FePointLight>()
+ .transform(ctx),
+ NodeType::FeSpotLight => node
+ .borrow_element()
+ .get_impl::<FeSpotLight>()
+ .transform(ctx),
_ => unreachable!(),
};
diff --git a/rsvg_internals/src/filters/merge.rs b/rsvg_internals/src/filters/merge.rs
index c70975f2..ddaac9d1 100644
--- a/rsvg_internals/src/filters/merge.rs
+++ b/rsvg_internals/src/filters/merge.rs
@@ -2,7 +2,7 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
-use crate::node::{NodeResult, NodeTrait, NodeType, RsvgNode};
+use crate::node::{NodeBorrow, NodeResult, NodeTrait, NodeType, RsvgNode};
use crate::parsers::ParseValue;
use crate::property_bag::PropertyBag;
use crate::rect::IRect;
@@ -92,14 +92,16 @@ impl FilterEffect for FeMerge {
.children()
.filter(|c| c.borrow().get_type() == NodeType::FeMergeNode)
{
- if child.borrow().is_in_error() {
+ let elt = child.borrow_element();
+
+ if elt.is_in_error() {
return Err(FilterError::ChildNodeInError);
}
let input = ctx.get_input(
acquired_nodes,
draw_ctx,
- child.borrow().get_impl::<FeMergeNode>().in_.as_ref(),
+ elt.get_impl::<FeMergeNode>().in_.as_ref(),
)?;
bounds = bounds.add_input(&input);
}
@@ -111,7 +113,7 @@ impl FilterEffect for FeMerge {
.children()
.filter(|c| c.borrow().get_type() == NodeType::FeMergeNode)
{
- output_surface = Some(child.borrow().get_impl::<FeMergeNode>().render(
+ output_surface = Some(child.borrow_element().get_impl::<FeMergeNode>().render(
ctx,
acquired_nodes,
draw_ctx,
diff --git a/rsvg_internals/src/filters/mod.rs b/rsvg_internals/src/filters/mod.rs
index 79f61572..d3aee6d7 100644
--- a/rsvg_internals/src/filters/mod.rs
+++ b/rsvg_internals/src/filters/mod.rs
@@ -12,7 +12,7 @@ use crate::drawing_ctx::DrawingCtx;
use crate::error::{RenderingError, ValueErrorKind};
use crate::filter::Filter;
use crate::length::*;
-use crate::node::{CascadedValues, NodeResult, NodeTrait, NodeType, RsvgNode};
+use crate::node::{CascadedValues, NodeBorrow, NodeResult, NodeTrait, NodeType, RsvgNode};
use crate::parsers::ParseValue;
use crate::properties::ComputedValues;
use crate::property_bag::PropertyBag;
@@ -118,7 +118,12 @@ impl NodeTrait for Primitive {
let primitiveunits = parent
.and_then(|parent| {
if parent.borrow().get_type() == NodeType::Filter {
- Some(parent.borrow().get_impl::<Filter>().get_primitive_units())
+ Some(
+ parent
+ .borrow_element()
+ .get_impl::<Filter>()
+ .get_primitive_units(),
+ )
} else {
None
}
@@ -248,8 +253,8 @@ pub fn render(
node_bbox: BoundingBox,
) -> Result<SharedImageSurface, RenderingError> {
let filter_node = &*filter_node;
- assert_eq!(filter_node.borrow().get_type(), NodeType::Filter);
- assert!(!filter_node.borrow().is_in_error());
+ assert_eq!(filter_node.borrow_element().get_type(), NodeType::Filter);
+ assert!(!filter_node.borrow_element().is_in_error());
let mut filter_ctx = FilterContext::new(
filter_node,
@@ -267,9 +272,10 @@ pub fn render(
let primitives = filter_node
.children()
+ .filter(|c| c.is_element())
// Skip nodes in error.
.filter(|c| {
- let in_error = c.borrow().is_in_error();
+ let in_error = c.borrow_element().is_in_error();
if in_error {
rsvg_log!("(ignoring filter primitive {} because it is in error)", c);
@@ -278,7 +284,12 @@ pub fn render(
!in_error
})
// Keep only filter primitives (those that implement the Filter trait)
- .filter(|c| c.borrow().get_node_trait().as_filter_effect().is_some())
+ .filter(|c| {
+ c.borrow_element()
+ .get_node_trait()
+ .as_filter_effect()
+ .is_some()
+ })
// Check if the node wants linear RGB.
.map(|c| {
let linear_rgb = {
@@ -292,8 +303,8 @@ pub fn render(
});
for (c, linear_rgb) in primitives {
- let node_data = c.borrow();
- let filter = node_data.get_node_trait().as_filter_effect().unwrap();
+ let elt = c.borrow_element();
+ let filter = elt.get_node_trait().as_filter_effect().unwrap();
let mut render = |filter_ctx: &mut FilterContext| {
if let Err(err) = filter
diff --git a/rsvg_internals/src/gradient.rs b/rsvg_internals/src/gradient.rs
index db44c184..fe46f4fb 100644
--- a/rsvg_internals/src/gradient.rs
+++ b/rsvg_internals/src/gradient.rs
@@ -11,7 +11,7 @@ use crate::document::{AcquiredNode, AcquiredNodes, NodeStack};
use crate::drawing_ctx::{DrawingCtx, ViewParams};
use crate::error::*;
use crate::length::*;
-use crate::node::{CascadedValues, NodeResult, NodeTrait, NodeType, RsvgNode};
+use crate::node::{CascadedValues, NodeBorrow, NodeResult, NodeTrait, NodeType, RsvgNode};
use crate::paint_server::{AsPaintSource, PaintSource};
use crate::parsers::{Parse, ParseValue};
use crate::properties::ComputedValues;
@@ -448,8 +448,8 @@ impl UnresolvedGradient {
assert!(node_type == NodeType::LinearGradient || node_type == NodeType::RadialGradient);
- for child_node in node.children() {
- let child = child_node.borrow();
+ for child_node in node.children().filter(|c| c.is_element()) {
+ let child = child_node.borrow_element();
if child.get_type() != NodeType::Stop {
continue;
@@ -661,7 +661,7 @@ macro_rules! impl_paint_source {
return Err(AcquireError::CircularReference(acquired_node.clone()));
}
- let borrowed_node = acquired_node.borrow();
+ let borrowed_node = acquired_node.borrow_element();
let unresolved = match borrowed_node.get_type() {
$node_type => {
let a_gradient = borrowed_node.get_impl::<$gradient>();
@@ -851,7 +851,7 @@ mod tests {
Box::new(LinearGradient::default()),
));
- let borrow = node.borrow();
+ let borrow = node.borrow_element();
let g = borrow.get_impl::<LinearGradient>();
let Unresolved { gradient, .. } = g.get_unresolved(&node);
let gradient = gradient.resolve_from_defaults();
@@ -865,7 +865,7 @@ mod tests {
Box::new(RadialGradient::default()),
));
- let borrow = node.borrow();
+ let borrow = node.borrow_element();
let g = borrow.get_impl::<RadialGradient>();
let Unresolved { gradient, .. } = g.get_unresolved(&node);
let gradient = gradient.resolve_from_defaults();
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index a615654d..87b7fc5f 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -14,7 +14,7 @@ use crate::document::{AcquiredNodes, Document};
use crate::dpi::Dpi;
use crate::drawing_ctx::DrawingCtx;
use crate::error::{DefsLookupErrorKind, LoadingError, RenderingError};
-use crate::node::{CascadedValues, RsvgNode};
+use crate::node::{CascadedValues, NodeBorrow, RsvgNode};
use crate::rect::{IRect, Rect};
use crate::structure::{IntrinsicDimensions, Svg};
use url::Url;
@@ -334,8 +334,10 @@ impl Handle {
let cascaded = CascadedValues::new_from_node(&node);
let values = cascaded.get();
- if let Some((root_width, root_height)) =
- node.borrow().get_impl::<Svg>().get_size(&values, dpi)
+ if let Some((root_width, root_height)) = node
+ .borrow_element()
+ .get_impl::<Svg>()
+ .get_size(&values, dpi)
{
let rect = IRect::from_size(root_width, root_height);
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index bac0efc3..5f716c24 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -573,7 +573,7 @@ fn emit_marker_by_name(
if let Ok(acquired) = acquired_nodes.acquire(name, &[NodeType::Marker]) {
let node = acquired.get();
- node.borrow().get_impl::<Marker>().render(
+ node.borrow_element().get_impl::<Marker>().render(
&node,
acquired_nodes,
draw_ctx,
diff --git a/rsvg_internals/src/node.rs b/rsvg_internals/src/node.rs
index 8ee42567..e44abffc 100644
--- a/rsvg_internals/src/node.rs
+++ b/rsvg_internals/src/node.rs
@@ -14,8 +14,8 @@
use downcast_rs::*;
use locale_config::Locale;
-use markup5ever::{expanded_name, local_name, namespace_url, ns, LocalName, Namespace, QualName};
-use std::cell::Ref;
+use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
+use std::cell::{Ref, RefMut};
use std::collections::HashSet;
use std::fmt;
@@ -43,8 +43,13 @@ pub type RsvgNode = rctree::Node<NodeData>;
/// See the [module documentation](index.html) for more information.
pub type RsvgWeakNode = rctree::WeakNode<NodeData>;
-/// Contents of a tree node
-pub struct NodeData {
+pub enum NodeData {
+ Element(Element),
+ Text(NodeChars),
+}
+
+/// Contents of an element node in the DOM
+pub struct Element {
node_type: NodeType,
element_name: QualName,
id: Option<String>, // id attribute from XML element
@@ -67,7 +72,7 @@ impl NodeData {
class: Option<&str>,
node_impl: Box<dyn NodeTrait>,
) -> NodeData {
- NodeData {
+ NodeData::Element(Element {
node_type,
element_name: element_name.clone(),
id: id.map(str::to_string),
@@ -80,21 +85,24 @@ impl NodeData {
cond: true,
style_attr: String::new(),
node_impl,
- }
+ })
}
pub fn new_chars() -> NodeData {
- Self::new_element(
- NodeType::Chars,
- &QualName::new(
- None,
- Namespace::from("https://wiki.gnome.org/Projects/LibRsvg"),
- LocalName::from("rsvg-chars"),
- ),
- None,
- None,
- Box::new(NodeChars::new()),
- )
+ NodeData::Text(NodeChars::new())
+ }
+
+ pub fn get_type(&self) -> NodeType {
+ match *self {
+ NodeData::Element(ref e) => e.node_type,
+ NodeData::Text(_) => NodeType::Chars,
+ }
+ }
+}
+
+impl Element {
+ pub fn get_type(&self) -> NodeType {
+ self.node_type
}
pub fn get_node_trait(&self) -> &dyn NodeTrait {
@@ -109,14 +117,6 @@ impl NodeData {
}
}
- pub fn get_type(&self) -> NodeType {
- self.node_type
- }
-
- pub fn get_chars(&self) -> &NodeChars {
- self.get_impl::<NodeChars>()
- }
-
pub fn element_name(&self) -> &QualName {
&self.element_name
}
@@ -280,12 +280,25 @@ impl NodeData {
impl fmt::Display for NodeData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(
- f,
- "{:?} id={}",
- self.get_type(),
- self.get_id().unwrap_or("None")
- )
+ write!(f, "{:?}", self.get_type())?;
+
+ match *self {
+ NodeData::Element(ref e) => {
+ write!(f, " id={}", e.get_id().unwrap_or("None"))?;
+ }
+
+ _ => (),
+ }
+
+ Ok(())
+ }
+}
+
+impl fmt::Display for Element {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{:?}", self.get_type())?;
+ write!(f, " id={}", self.get_id().unwrap_or("None"))?;
+ Ok(())
}
}
@@ -304,7 +317,7 @@ pub struct CascadedValues<'a> {
}
enum CascadedInner<'a> {
- FromNode(Ref<'a, NodeData>),
+ FromNode(Ref<'a, Element>),
FromValues(ComputedValues),
}
@@ -317,7 +330,7 @@ impl<'a> CascadedValues<'a> {
pub fn new(&self, node: &'a RsvgNode) -> CascadedValues<'a> {
match self.inner {
CascadedInner::FromNode(_) => CascadedValues {
- inner: CascadedInner::FromNode(node.borrow()),
+ inner: CascadedInner::FromNode(node.borrow_element()),
},
CascadedInner::FromValues(ref v) => CascadedValues::new_from_values(node, v),
@@ -331,7 +344,7 @@ impl<'a> CascadedValues<'a> {
/// `new()` to derive the cascade from an existing one.
pub fn new_from_node(node: &RsvgNode) -> CascadedValues<'_> {
CascadedValues {
- inner: CascadedInner::FromNode(node.borrow()),
+ inner: CascadedInner::FromNode(node.borrow_element()),
}
}
@@ -342,7 +355,9 @@ impl<'a> CascadedValues<'a> {
/// `<use>`'s own cascade, not wih the element's original cascade.
pub fn new_from_values(node: &'a RsvgNode, values: &ComputedValues) -> CascadedValues<'a> {
let mut v = values.clone();
- node.borrow().specified_values.to_computed_values(&mut v);
+ node.borrow_element()
+ .specified_values
+ .to_computed_values(&mut v);
CascadedValues {
inner: CascadedInner::FromValues(v),
@@ -355,7 +370,7 @@ impl<'a> CascadedValues<'a> {
/// `ComputedValues` from the `CascadedValues` that got passed to `draw()`.
pub fn get(&'a self) -> &'a ComputedValues {
match self.inner {
- CascadedInner::FromNode(ref node) => &node.values,
+ CascadedInner::FromNode(ref element) => &element.values,
CascadedInner::FromValues(ref v) => v,
}
}
@@ -478,6 +493,57 @@ pub enum NodeType {
FeTurbulence,
}
+/// Helper trait to get different NodeData variants
+pub trait NodeBorrow {
+ /// Returns `false` for NodeData::Text, `true` otherwise.
+ fn is_element(&self) -> bool;
+
+ /// Borrows a `NodeChars` reference.
+ ///
+ /// Panics: will panic if `&self` is not a `NodeData::Text` node
+ fn borrow_chars(&self) -> Ref<NodeChars>;
+
+ /// Borrows an `Element` reference
+ ///
+ /// Panics: will panic if `&self` is not a `NodeData::Element` node
+ fn borrow_element(&self) -> Ref<Element>;
+
+ /// Borrows an `Element` reference mutably
+ ///
+ /// Panics: will panic if `&self` is not a `NodeData::Element` node
+ fn borrow_element_mut(&mut self) -> RefMut<Element>;
+}
+
+impl NodeBorrow for RsvgNode {
+ fn is_element(&self) -> bool {
+ match *self.borrow() {
+ NodeData::Element(_) => true,
+ _ => false,
+ }
+ }
+
+ fn borrow_chars(&self) -> Ref<NodeChars> {
+ Ref::map(self.borrow(), |n| match *n {
+ NodeData::Text(ref c) => c,
+ _ => panic!("tried to borrow_chars for a non-text node"),
+ })
+ }
+
+ fn borrow_element(&self) -> Ref<Element> {
+ Ref::map(self.borrow(), |n| match *n {
+ NodeData::Element(ref e) => e,
+ _ => panic!("tried to borrow_element for a non-element node"),
+ })
+ }
+
+ fn borrow_element_mut(&mut self) -> RefMut<Element> {
+ RefMut::map(self.borrow_mut(), |n| match *n {
+ NodeData::Element(ref mut e) => e,
+ _ => panic!("tried to borrow_element_mut for a non-element node"),
+ })
+ }
+}
+
/// Helper trait for cascading recursively
pub trait NodeCascade {
fn cascade(&mut self, values: &ComputedValues);
@@ -488,13 +554,13 @@ impl NodeCascade for RsvgNode {
let mut values = values.clone();
{
- let mut node_mut = self.borrow_mut();
+ let mut elt = self.borrow_element_mut();
- node_mut.specified_values.to_computed_values(&mut values);
- node_mut.values = values.clone();
+ elt.specified_values.to_computed_values(&mut values);
+ elt.values = values.clone();
}
- for mut child in self.children() {
+ for mut child in self.children().filter(|c| c.is_element()) {
child.cascade(&values);
}
}
@@ -527,18 +593,23 @@ impl NodeDraw for RsvgNode {
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
- if !self.borrow().is_in_error() {
- let transform = self.borrow().get_transform();
- draw_ctx.with_saved_transform(Some(transform), &mut |dc| {
- self.borrow()
- .get_node_trait()
- .draw(self, acquired_nodes, cascaded, dc, clipping)
- })
- } else {
- rsvg_log!("(not rendering element {} because it is in error)", self);
+ match *self.borrow() {
+ NodeData::Element(ref e) => {
+ if !e.is_in_error() {
+ let transform = e.get_transform();
+ draw_ctx.with_saved_transform(Some(transform), &mut |dc| {
+ e.get_node_trait()
+ .draw(self, acquired_nodes, cascaded, dc, clipping)
+ })
+ } else {
+ rsvg_log!("(not rendering element {} because it is in error)", self);
+
+ // maybe we should actually return a RenderingError::NodeIsInError here?
+ Ok(draw_ctx.empty_bbox())
+ }
+ }
- // maybe we should actually return a RenderingError::NodeIsInError here?
- Ok(draw_ctx.empty_bbox())
+ _ => Ok(draw_ctx.empty_bbox()),
}
}
@@ -551,7 +622,7 @@ impl NodeDraw for RsvgNode {
) -> Result<BoundingBox, RenderingError> {
let mut bbox = draw_ctx.empty_bbox();
- for child in self.children() {
+ for child in self.children().filter(|c| c.is_element()) {
let child_bbox = draw_ctx.draw_node_from_stack(
&child,
acquired_nodes,
diff --git a/rsvg_internals/src/pattern.rs b/rsvg_internals/src/pattern.rs
index 2eef1a8e..beaa484e 100644
--- a/rsvg_internals/src/pattern.rs
+++ b/rsvg_internals/src/pattern.rs
@@ -188,7 +188,7 @@ impl PaintSource for Pattern {
return Err(AcquireError::CircularReference(acquired_node.clone()));
}
- let borrowed_node = acquired_node.borrow();
+ let borrowed_node = acquired_node.borrow_element();
let borrowed_pattern = borrowed_node.get_impl::<Pattern>();
let unresolved = borrowed_pattern.get_unresolved(&acquired_node);
@@ -478,10 +478,7 @@ impl UnresolvedChildren {
fn from_node(node: &RsvgNode) -> UnresolvedChildren {
let weak = node.downgrade();
- if node
- .children()
- .any(|child| child.borrow().get_type() != NodeType::Chars)
- {
+ if node.children().any(|child| child.is_element()) {
UnresolvedChildren::WithChildren(weak)
} else {
UnresolvedChildren::Unresolved
@@ -578,7 +575,7 @@ mod tests {
Box::new(Pattern::default()),
));
- let borrow = node.borrow();
+ let borrow = node.borrow_element();
let p = borrow.get_impl::<Pattern>();
let Unresolved { pattern, .. } = p.get_unresolved(&node);
let pattern = pattern.resolve_from_defaults();
diff --git a/rsvg_internals/src/structure.rs b/rsvg_internals/src/structure.rs
index a1034f97..e87992c5 100644
--- a/rsvg_internals/src/structure.rs
+++ b/rsvg_internals/src/structure.rs
@@ -76,8 +76,8 @@ impl NodeTrait for Switch {
draw_ctx.with_discrete_layer(node, acquired_nodes, values, clipping, &mut |an, dc| {
if let Some(child) = node
.children()
- .filter(|c| c.borrow().get_type() != NodeType::Chars)
- .find(|c| c.borrow().get_cond())
+ .filter(|c| c.is_element())
+ .find(|c| c.borrow_element().get_cond())
{
dc.draw_node_from_stack(
&child,
diff --git a/rsvg_internals/src/text.rs b/rsvg_internals/src/text.rs
index e59af753..cc2c2369 100644
--- a/rsvg_internals/src/text.rs
+++ b/rsvg_internals/src/text.rs
@@ -12,7 +12,7 @@ use crate::error::*;
use crate::float_eq_cairo::ApproxEqCairo;
use crate::font_props::FontWeightSpec;
use crate::length::*;
-use crate::node::{CascadedValues, NodeResult, NodeTrait, NodeType, RsvgNode};
+use crate::node::{CascadedValues, NodeBorrow, NodeResult, NodeTrait, NodeType, RsvgNode};
use crate::parsers::ParseValue;
use crate::properties::ComputedValues;
use crate::property_bag::PropertyBag;
@@ -432,14 +432,13 @@ fn children_to_chunks(
NodeType::Chars => {
let values = cascaded.get();
child
- .borrow()
- .get_chars()
+ .borrow_chars()
.to_chunks(&child, values, chunks, dx, dy, depth);
}
NodeType::TSpan => {
let cascaded = CascadedValues::new(cascaded, &child);
- child.borrow().get_impl::<TSpan>().to_chunks(
+ child.borrow_element().get_impl::<TSpan>().to_chunks(
&child,
acquired_nodes,
&cascaded,
@@ -451,7 +450,7 @@ fn children_to_chunks(
NodeType::TRef => {
let cascaded = CascadedValues::new(cascaded, &child);
- child.borrow().get_impl::<TRef>().to_chunks(
+ child.borrow_element().get_impl::<TRef>().to_chunks(
&child,
acquired_nodes,
&cascaded,
@@ -568,12 +567,6 @@ impl NodeChars {
}
}
-impl NodeTrait for NodeChars {
- fn set_atts(&mut self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> NodeResult {
- Ok(())
- }
-}
-
#[derive(Default)]
pub struct Text {
x: Length<Horizontal>,
@@ -717,9 +710,9 @@ fn extract_chars_children_to_chunks_recursively(
for child in node.children() {
match child.borrow().get_type() {
NodeType::Chars => child
- .borrow()
- .get_chars()
+ .borrow_chars()
.to_chunks(&child, values, chunks, None, None, depth),
+
_ => extract_chars_children_to_chunks_recursively(chunks, &child, values, depth + 1),
}
}
diff --git a/rsvg_internals/src/xml.rs b/rsvg_internals/src/xml.rs
index 2a61c2a6..f83f8017 100644
--- a/rsvg_internals/src/xml.rs
+++ b/rsvg_internals/src/xml.rs
@@ -16,7 +16,7 @@ use crate::document::{Document, DocumentBuilder};
use crate::error::LoadingError;
use crate::io::{self, get_input_stream_for_loading};
use crate::limits::MAX_LOADED_ELEMENTS;
-use crate::node::{NodeType, RsvgNode};
+use crate::node::{NodeBorrow, NodeType, RsvgNode};
use crate::property_bag::PropertyBag;
use crate::style::{Style, StyleType};
use crate::xml2_load::Xml2Parser;
@@ -361,7 +361,7 @@ impl XmlState {
assert!(current_node.borrow().get_type() == NodeType::Style);
let style_type = current_node
- .borrow()
+ .borrow_element()
.get_impl::<Style>()
.style_type()
.unwrap_or(StyleType::TextCss);
@@ -370,10 +370,10 @@ impl XmlState {
let stylesheet_text = current_node
.children()
.map(|child| {
- let child_borrow = child.borrow();
-
- assert!(child_borrow.get_type() == NodeType::Chars);
- child_borrow.get_chars().get_string()
+ // Note that here we assume that the only children of <style>
+ // are indeed text nodes.
+ let child_borrow = child.borrow_chars();
+ child_borrow.get_string()
})
.collect::<String>();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]