summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@gnome.org>2023-02-22 18:24:33 -0600
committerFederico Mena Quintero <federico@gnome.org>2023-02-27 16:44:17 -0600
commit9a76330749f6d6a57d1b935d9a00c806ec8adb05 (patch)
treedc80faf5fe56dd4c147df2759e417b5452af67ce
parent9688c442880e848302d1ee32c73c273767539bf5 (diff)
downloadlibrsvg-9a76330749f6d6a57d1b935d9a00c806ec8adb05.tar.gz
Remove ElementInner<T> and replace it with an ElementData enum
We had this structure: enum Element { Circle(Box<ElementInner<Circle>>), // ... all the supported elements } struct ElementInner<T> { // fields to hold element's name, attributes, SpecifiedValues, etc. element_impl: T } However, "impl ElementInner" has a little bunch of methods, which get monomorphized for each supported element type. These methods don't do anything with the "element_impl: T". Instead, we now have this structure: struct Element { // fields to hold element's name, attributes, SpecifiedValues, etc. element_data: ElementData, } enum ElementData { Circle(Box<Circle>), // ... all the supported elements } The Circle inside the Box, and all the other structs for element types, implement ElementTrait which has the ::draw() method. I'm using concrete types inside the boxes, not Box<ElementTrait>, to avoid having to downcast to the concrete type. The only place that dispatches dynamically is ElementData::draw(). The call_inner!() macro goes away, since it doesn't need to delegate things to the ElementInner any more. All the interesting stuff happens directly in struct Element. The rest of the code doesn't need too many changes, since all the borrowing and type checking happens in the NodeBorrow trait - its borrow_element*() methods, and the macros is_element_of_type!() and borrow_element_as!(). Together with the previous commit that simplifies feComponentTransfer, this removes 186912 bytes from the .text section of rsvg-convert (per objdump's numbers). Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/801>
-rw-r--r--src/css.rs4
-rw-r--r--src/drawing_ctx.rs37
-rw-r--r--src/element.rs635
-rw-r--r--src/filter.rs7
-rw-r--r--src/filters/component_transfer.rs8
-rw-r--r--src/filters/lighting.rs25
-rw-r--r--src/filters/merge.rs8
-rw-r--r--src/gradient.rs16
-rw-r--r--src/layout.rs10
-rw-r--r--src/node.rs44
-rw-r--r--src/paint_server.rs10
-rw-r--r--src/pattern.rs6
-rw-r--r--src/structure.rs4
-rw-r--r--src/text.rs10
14 files changed, 320 insertions, 504 deletions
diff --git a/src/css.rs b/src/css.rs
index 0a8ddf0e..bf81dddf 100644
--- a/src/css.rs
+++ b/src/css.rs
@@ -675,8 +675,8 @@ impl selectors::Element for RsvgElement {
// a link, so to avoid nasty surprises, we do the same.
// Empty href's, however, ARE considered links.
self.0.is_element()
- && match &*self.0.borrow_element() {
- crate::element::Element::Link(link) => link.link.is_some(),
+ && match *self.0.borrow_element_data() {
+ crate::element::ElementData::Link(ref link) => link.link.is_some(),
_ => false,
}
}
diff --git a/src/drawing_ctx.rs b/src/drawing_ctx.rs
index a50ab36f..e3b9649f 100644
--- a/src/drawing_ctx.rs
+++ b/src/drawing_ctx.rs
@@ -20,7 +20,7 @@ use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNodes, NodeId};
use crate::dpi::Dpi;
-use crate::element::Element;
+use crate::element::{Element, ElementData};
use crate::error::{AcquireError, ImplementationLimit, RenderingError};
use crate::filter::FilterValueList;
use crate::filters::{self, FilterSpec};
@@ -1946,32 +1946,29 @@ pub fn pango_layout_to_path(
// https://www.w3.org/TR/css-masking-1/#ClipPathElement
fn element_can_be_used_inside_clip_path(element: &Element) -> bool {
+ use ElementData::*;
+
matches!(
- *element,
- Element::Circle(_)
- | Element::Ellipse(_)
- | Element::Line(_)
- | Element::Path(_)
- | Element::Polygon(_)
- | Element::Polyline(_)
- | Element::Rect(_)
- | Element::Text(_)
- | Element::Use(_)
+ element.element_data,
+ Circle(_)
+ | Ellipse(_)
+ | Line(_)
+ | Path(_)
+ | Polygon(_)
+ | Polyline(_)
+ | Rect(_)
+ | Text(_)
+ | Use(_)
)
}
// https://www.w3.org/TR/css-masking-1/#ClipPathElement
fn element_can_be_used_inside_use_inside_clip_path(element: &Element) -> bool {
+ use ElementData::*;
+
matches!(
- *element,
- Element::Circle(_)
- | Element::Ellipse(_)
- | Element::Line(_)
- | Element::Path(_)
- | Element::Polygon(_)
- | Element::Polyline(_)
- | Element::Rect(_)
- | Element::Text(_)
+ element.element_data,
+ Circle(_) | Ellipse(_) | Line(_) | Path(_) | Polygon(_) | Polyline(_) | Rect(_) | Text(_)
)
}
diff --git a/src/element.rs b/src/element.rs
index 4d97c454..946cab0d 100644
--- a/src/element.rs
+++ b/src/element.rs
@@ -4,7 +4,6 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
use once_cell::sync::Lazy;
use std::collections::{HashMap, HashSet};
use std::fmt;
-use std::ops::Deref;
use crate::accept_language::UserLanguage;
use crate::bbox::BoundingBox;
@@ -95,7 +94,7 @@ pub fn set_attribute<T>(dest: &mut T, parse_result: Result<T, ElementError>, ses
}
}
-pub struct ElementInner<T: ElementTrait> {
+pub struct Element {
element_name: QualName,
attributes: Attributes,
specified_values: SpecifiedValues,
@@ -104,18 +103,106 @@ pub struct ElementInner<T: ElementTrait> {
required_extensions: Option<RequiredExtensions>,
required_features: Option<RequiredFeatures>,
system_language: Option<SystemLanguage>,
- pub element_impl: T,
+ pub element_data: ElementData,
}
-impl<T: ElementTrait> ElementInner<T> {
- fn new(
- session: &Session,
- element_name: QualName,
- attributes: Attributes,
- element_impl: T,
- ) -> ElementInner<T> {
+impl fmt::Display for Element {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}", self.element_name().local)?;
+ write!(f, " id={}", self.get_id().unwrap_or("None"))?;
+ Ok(())
+ }
+}
+
+/// Parsed contents of an element node in the DOM.
+///
+/// This enum uses `Box<Foo>` in order to make each variant the size of
+/// a pointer.
+pub enum ElementData {
+ Circle(Box<Circle>),
+ ClipPath(Box<ClipPath>),
+ Ellipse(Box<Ellipse>),
+ Filter(Box<Filter>),
+ Group(Box<Group>),
+ Image(Box<Image>),
+ Line(Box<Line>),
+ LinearGradient(Box<LinearGradient>),
+ Link(Box<Link>),
+ Marker(Box<Marker>),
+ Mask(Box<Mask>),
+ NonRendering(Box<NonRendering>),
+ Path(Box<Path>),
+ Pattern(Box<Pattern>),
+ Polygon(Box<Polygon>),
+ Polyline(Box<Polyline>),
+ RadialGradient(Box<RadialGradient>),
+ Rect(Box<Rect>),
+ Stop(Box<Stop>),
+ Style(Box<Style>),
+ Svg(Box<Svg>),
+ Switch(Box<Switch>),
+ Symbol(Box<Symbol>),
+ Text(Box<Text>),
+ TRef(Box<TRef>),
+ TSpan(Box<TSpan>),
+ Use(Box<Use>),
+
+ // Filter primitives, these start with "Fe" as element names are e.g. "feBlend"
+ FeBlend(Box<FeBlend>),
+ FeColorMatrix(Box<FeColorMatrix>),
+ FeComponentTransfer(Box<FeComponentTransfer>),
+ FeComposite(Box<FeComposite>),
+ FeConvolveMatrix(Box<FeConvolveMatrix>),
+ FeDiffuseLighting(Box<FeDiffuseLighting>),
+ FeDisplacementMap(Box<FeDisplacementMap>),
+ FeDistantLight(Box<FeDistantLight>),
+ FeDropShadow(Box<FeDropShadow>),
+ FeFlood(Box<FeFlood>),
+ FeFuncA(Box<FeFuncA>),
+ FeFuncB(Box<FeFuncB>),
+ FeFuncG(Box<FeFuncG>),
+ FeFuncR(Box<FeFuncR>),
+ FeGaussianBlur(Box<FeGaussianBlur>),
+ FeImage(Box<FeImage>),
+ FeMerge(Box<FeMerge>),
+ FeMergeNode(Box<FeMergeNode>),
+ FeMorphology(Box<FeMorphology>),
+ FeOffset(Box<FeOffset>),
+ FePointLight(Box<FePointLight>),
+ FeSpecularLighting(Box<FeSpecularLighting>),
+ FeSpotLight(Box<FeSpotLight>),
+ FeTile(Box<FeTile>),
+ FeTurbulence(Box<FeTurbulence>),
+}
+
+impl Element {
+ /// Takes an XML element name and consumes a list of attribute/value pairs to create an [`Element`].
+ ///
+ /// This operation does not fail. Unknown element names simply produce a [`NonRendering`]
+ /// element.
+ pub fn new(session: &Session, name: &QualName, mut attributes: Attributes) -> Element {
+ let (create_fn, flags): (ElementDataCreateFn, ElementCreateFlags) = if name.ns == ns!(svg) {
+ match ELEMENT_CREATORS.get(name.local.as_ref()) {
+ // hack in the SVG namespace for supported element names
+ Some(&(create_fn, flags)) => (create_fn, flags),
+
+ // Whenever we encounter a element name we don't understand, represent it as a
+ // non-rendering element. This is like a group, but it doesn't do any rendering
+ // of children. The effect is that we will ignore all children of unknown elements.
+ None => (create_non_rendering, ElementCreateFlags::Default),
+ }
+ } else {
+ (create_non_rendering, ElementCreateFlags::Default)
+ };
+
+ if flags == ElementCreateFlags::IgnoreClass {
+ attributes.clear_class();
+ };
+
+ let element_data = create_fn(session, &attributes);
+
let mut e = Self {
- element_name,
+ element_name: name.clone(),
attributes,
specified_values: Default::default(),
important_styles: Default::default(),
@@ -123,7 +210,7 @@ impl<T: ElementTrait> ElementInner<T> {
required_extensions: Default::default(),
required_features: Default::default(),
system_language: Default::default(),
- element_impl,
+ element_data,
};
e.set_conditional_processing_attributes(session);
@@ -132,40 +219,40 @@ impl<T: ElementTrait> ElementInner<T> {
e
}
- fn element_name(&self) -> &QualName {
+ pub fn element_name(&self) -> &QualName {
&self.element_name
}
- fn get_attributes(&self) -> &Attributes {
+ pub fn get_attributes(&self) -> &Attributes {
&self.attributes
}
- fn get_id(&self) -> Option<&str> {
+ pub fn get_id(&self) -> Option<&str> {
self.attributes.get_id()
}
- fn get_class(&self) -> Option<&str> {
+ pub fn get_class(&self) -> Option<&str> {
self.attributes.get_class()
}
- fn inherit_xml_lang(&mut self, parent: Option<Node>) {
+ pub fn inherit_xml_lang(&mut self, parent: Option<Node>) {
self.specified_values
.inherit_xml_lang(&mut self.values, parent);
}
- fn get_specified_values(&self) -> &SpecifiedValues {
+ pub fn get_specified_values(&self) -> &SpecifiedValues {
&self.specified_values
}
- fn get_computed_values(&self) -> &ComputedValues {
+ pub fn get_computed_values(&self) -> &ComputedValues {
&self.values
}
- fn set_computed_values(&mut self, values: &ComputedValues) {
+ pub fn set_computed_values(&mut self, values: &ComputedValues) {
self.values = values.clone();
}
- fn get_cond(&self, user_language: &UserLanguage) -> bool {
+ pub fn get_cond(&self, user_language: &UserLanguage) -> bool {
self.required_extensions
.as_ref()
.map(|v| v.eval())
@@ -209,7 +296,7 @@ impl<T: ElementTrait> ElementInner<T> {
}
// Applies a style declaration to the node's specified_values
- fn apply_style_declaration(&mut self, declaration: &Declaration, origin: Origin) {
+ pub fn apply_style_declaration(&mut self, declaration: &Declaration, origin: Origin) {
self.specified_values.set_property_from_declaration(
declaration,
origin,
@@ -218,7 +305,7 @@ impl<T: ElementTrait> ElementInner<T> {
}
/// Applies CSS styles from the "style" attribute
- fn set_style_attribute(&mut self, session: &Session) {
+ pub fn set_style_attribute(&mut self, session: &Session) {
let style = self
.attributes
.iter()
@@ -234,10 +321,53 @@ impl<T: ElementTrait> ElementInner<T> {
);
}
}
-}
-impl<T: ElementTrait> ElementTrait for ElementInner<T> {
- fn draw(
+ #[rustfmt::skip]
+ pub fn as_filter_effect(&self) -> Option<&dyn FilterEffect> {
+ use ElementData::*;
+
+ match &self.element_data {
+ FeBlend(fe) => Some(&**fe),
+ FeColorMatrix(fe) => Some(&**fe),
+ FeComponentTransfer(fe) => Some(&**fe),
+ FeComposite(fe) => Some(&**fe),
+ FeConvolveMatrix(fe) => Some(&**fe),
+ FeDiffuseLighting(fe) => Some(&**fe),
+ FeDisplacementMap(fe) => Some(&**fe),
+ FeDropShadow(fe) => Some(&**fe),
+ FeFlood(fe) => Some(&**fe),
+ FeGaussianBlur(fe) => Some(&**fe),
+ FeImage(fe) => Some(&**fe),
+ FeMerge(fe) => Some(&**fe),
+ FeMorphology(fe) => Some(&**fe),
+ FeOffset(fe) => Some(&**fe),
+ FeSpecularLighting(fe) => Some(&**fe),
+ FeTile(fe) => Some(&**fe),
+ FeTurbulence(fe) => Some(&**fe),
+ _ => None,
+ }
+ }
+
+ /// Returns whether an element of a particular type is only accessed by reference
+ // from other elements' attributes. The element could in turn cause other nodes
+ // to get referenced, potentially causing reference cycles.
+ pub fn is_accessed_by_reference(&self) -> bool {
+ use ElementData::*;
+
+ matches!(
+ self.element_data,
+ ClipPath(_)
+ | Filter(_)
+ | LinearGradient(_)
+ | Marker(_)
+ | Mask(_)
+ | Pattern(_)
+ | RadialGradient(_)
+ )
+ }
+
+ /// The main drawing function for elements.
+ pub fn draw(
&self,
node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
@@ -247,7 +377,7 @@ impl<T: ElementTrait> ElementTrait for ElementInner<T> {
) -> Result<BoundingBox, RenderingError> {
let values = cascaded.get();
if values.is_displayed() {
- self.element_impl
+ self.element_data
.draw(node, acquired_nodes, cascaded, draw_ctx, clipping)
} else {
Ok(draw_ctx.empty_bbox())
@@ -255,278 +385,9 @@ impl<T: ElementTrait> ElementTrait for ElementInner<T> {
}
}
-impl<T: ElementTrait> fmt::Display for ElementInner<T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}", self.element_name().local)?;
- write!(f, " id={}", self.get_id().unwrap_or("None"))?;
- Ok(())
- }
-}
-
-impl<T: ElementTrait> Deref for ElementInner<T> {
- type Target = T;
-
- #[inline]
- fn deref(&self) -> &Self::Target {
- &self.element_impl
- }
-}
-
-/// Contents of an element node in the DOM
-/// This enum uses `Box<ElementInner>` in order to make each `Element`
-/// the size of a pointer.
-
-pub enum Element {
- Circle(Box<ElementInner<Circle>>),
- ClipPath(Box<ElementInner<ClipPath>>),
- Ellipse(Box<ElementInner<Ellipse>>),
- Filter(Box<ElementInner<Filter>>),
- Group(Box<ElementInner<Group>>),
- Image(Box<ElementInner<Image>>),
- Line(Box<ElementInner<Line>>),
- LinearGradient(Box<ElementInner<LinearGradient>>),
- Link(Box<ElementInner<Link>>),
- Marker(Box<ElementInner<Marker>>),
- Mask(Box<ElementInner<Mask>>),
- NonRendering(Box<ElementInner<NonRendering>>),
- Path(Box<ElementInner<Path>>),
- Pattern(Box<ElementInner<Pattern>>),
- Polygon(Box<ElementInner<Polygon>>),
- Polyline(Box<ElementInner<Polyline>>),
- RadialGradient(Box<ElementInner<RadialGradient>>),
- Rect(Box<ElementInner<Rect>>),
- Stop(Box<ElementInner<Stop>>),
- Style(Box<ElementInner<Style>>),
- Svg(Box<ElementInner<Svg>>),
- Switch(Box<ElementInner<Switch>>),
- Symbol(Box<ElementInner<Symbol>>),
- Text(Box<ElementInner<Text>>),
- TRef(Box<ElementInner<TRef>>),
- TSpan(Box<ElementInner<TSpan>>),
- Use(Box<ElementInner<Use>>),
-
- // Filter primitives, these start with "Fe" as element names are e.g. "feBlend"
- FeBlend(Box<ElementInner<FeBlend>>),
- FeColorMatrix(Box<ElementInner<FeColorMatrix>>),
- FeComponentTransfer(Box<ElementInner<FeComponentTransfer>>),
- FeComposite(Box<ElementInner<FeComposite>>),
- FeConvolveMatrix(Box<ElementInner<FeConvolveMatrix>>),
- FeDiffuseLighting(Box<ElementInner<FeDiffuseLighting>>),
- FeDisplacementMap(Box<ElementInner<FeDisplacementMap>>),
- FeDistantLight(Box<ElementInner<FeDistantLight>>),
- FeDropShadow(Box<ElementInner<FeDropShadow>>),
- FeFlood(Box<ElementInner<FeFlood>>),
- FeFuncA(Box<ElementInner<FeFuncA>>),
- FeFuncB(Box<ElementInner<FeFuncB>>),
- FeFuncG(Box<ElementInner<FeFuncG>>),
- FeFuncR(Box<ElementInner<FeFuncR>>),
- FeGaussianBlur(Box<ElementInner<FeGaussianBlur>>),
- FeImage(Box<ElementInner<FeImage>>),
- FeMerge(Box<ElementInner<FeMerge>>),
- FeMergeNode(Box<ElementInner<FeMergeNode>>),
- FeMorphology(Box<ElementInner<FeMorphology>>),
- FeOffset(Box<ElementInner<FeOffset>>),
- FePointLight(Box<ElementInner<FePointLight>>),
- FeSpecularLighting(Box<ElementInner<FeSpecularLighting>>),
- FeSpotLight(Box<ElementInner<FeSpotLight>>),
- FeTile(Box<ElementInner<FeTile>>),
- FeTurbulence(Box<ElementInner<FeTurbulence>>),
-}
-
-macro_rules! call_inner {
- // end recursion, call the method
- ($element:ident, $method:ident [$($args:expr),*]) => {
- match $element {
- Element::Circle(i) => i.$method($($args),*),
- Element::ClipPath(i) => i.$method($($args),*),
- Element::Ellipse(i) => i.$method($($args),*),
- Element::Filter(i) => i.$method($($args),*),
- Element::Group(i) => i.$method($($args),*),
- Element::Image(i) => i.$method($($args),*),
- Element::Line(i) => i.$method($($args),*),
- Element::LinearGradient(i) => i.$method($($args),*),
- Element::Link(i) => i.$method($($args),*),
- Element::Marker(i) => i.$method($($args),*),
- Element::Mask(i) => i.$method($($args),*),
- Element::NonRendering(i) => i.$method($($args),*),
- Element::Path(i) => i.$method($($args),*),
- Element::Pattern(i) => i.$method($($args),*),
- Element::Polygon(i) => i.$method($($args),*),
- Element::Polyline(i) => i.$method($($args),*),
- Element::RadialGradient(i) => i.$method($($args),*),
- Element::Rect(i) => i.$method($($args),*),
- Element::Stop(i) => i.$method($($args),*),
- Element::Style(i) => i.$method($($args),*),
- Element::Svg(i) => i.$method($($args),*),
- Element::Switch(i) => i.$method($($args),*),
- Element::Symbol(i) => i.$method($($args),*),
- Element::Text(i) => i.$method($($args),*),
- Element::TRef(i) => i.$method($($args),*),
- Element::TSpan(i) => i.$method($($args),*),
- Element::Use(i) => i.$method($($args),*),
- Element::FeBlend(i) => i.$method($($args),*),
- Element::FeColorMatrix(i) => i.$method($($args),*),
- Element::FeComponentTransfer(i) => i.$method($($args),*),
- Element::FeComposite(i) => i.$method($($args),*),
- Element::FeConvolveMatrix(i) => i.$method($($args),*),
- Element::FeDiffuseLighting(i) => i.$method($($args),*),
- Element::FeDisplacementMap(i) => i.$method($($args),*),
- Element::FeDistantLight(i) => i.$method($($args),*),
- Element::FeDropShadow(i) => i.$method($($args),*),
- Element::FeFlood(i) => i.$method($($args),*),
- Element::FeFuncA(i) => i.$method($($args),*),
- Element::FeFuncB(i) => i.$method($($args),*),
- Element::FeFuncG(i) => i.$method($($args),*),
- Element::FeFuncR(i) => i.$method($($args),*),
- Element::FeGaussianBlur(i) => i.$method($($args),*),
- Element::FeImage(i) => i.$method($($args),*),
- Element::FeMerge(i) => i.$method($($args),*),
- Element::FeMergeNode(i) => i.$method($($args),*),
- Element::FeMorphology(i) => i.$method($($args),*),
- Element::FeOffset(i) => i.$method($($args),*),
- Element::FePointLight(i) => i.$method($($args),*),
- Element::FeSpecularLighting(i) => i.$method($($args),*),
- Element::FeSpotLight(i) => i.$method($($args),*),
- Element::FeTile(i) => i.$method($($args),*),
- Element::FeTurbulence(i) => i.$method($($args),*),
- }
- };
-
- // munch munch
- ($element:ident, $method:ident [$($args:expr),*] $arg:expr, $($rest:tt)*) => {
- call_inner!($element, $method [$($args,)*$arg] $($rest)*)
- };
-
- // entry point with args
- ($element:ident, $method:ident, $arg:expr, $($args:expr),*) => {
- call_inner!($element, $method [$arg] $($args,)*)
- };
-
- // entry point with one arg
- ($element:ident, $method:ident, $arg:expr) => {
- call_inner!($element, $method [$arg])
- };
-
- // entry point without args
- ($element:ident, $method:ident) => {
- call_inner!($element, $method [])
- };
-}
-
-impl Element {
- /// Takes an XML element name and consumes a list of attribute/value pairs to create an [`Element`].
- ///
- /// This operation does not fail. Unknown element names simply produce a [`NonRendering`]
- /// element.
- pub fn new(session: &Session, name: &QualName, mut attrs: Attributes) -> Element {
- let (create_fn, flags): (ElementCreateFn, ElementCreateFlags) = if name.ns == ns!(svg) {
- match ELEMENT_CREATORS.get(name.local.as_ref()) {
- // hack in the SVG namespace for supported element names
- Some(&(create_fn, flags)) => (create_fn, flags),
-
- // Whenever we encounter a element name we don't understand, represent it as a
- // non-rendering element. This is like a group, but it doesn't do any rendering
- // of children. The effect is that we will ignore all children of unknown elements.
- None => (create_non_rendering, ElementCreateFlags::Default),
- }
- } else {
- (create_non_rendering, ElementCreateFlags::Default)
- };
-
- if flags == ElementCreateFlags::IgnoreClass {
- attrs.clear_class();
- };
-
- // sizes::print_sizes();
-
- create_fn(session, name, attrs)
- }
-
- pub fn element_name(&self) -> &QualName {
- call_inner!(self, element_name)
- }
-
- pub fn get_attributes(&self) -> &Attributes {
- call_inner!(self, get_attributes)
- }
-
- pub fn get_id(&self) -> Option<&str> {
- call_inner!(self, get_id)
- }
-
- pub fn get_class(&self) -> Option<&str> {
- call_inner!(self, get_class)
- }
-
- pub fn inherit_xml_lang(&mut self, parent: Option<Node>) {
- call_inner!(self, inherit_xml_lang, parent)
- }
-
- pub fn get_specified_values(&self) -> &SpecifiedValues {
- call_inner!(self, get_specified_values)
- }
-
- pub fn get_computed_values(&self) -> &ComputedValues {
- call_inner!(self, get_computed_values)
- }
-
- pub fn set_computed_values(&mut self, values: &ComputedValues) {
- call_inner!(self, set_computed_values, values);
- }
-
- pub fn get_cond(&self, user_language: &UserLanguage) -> bool {
- call_inner!(self, get_cond, user_language)
- }
-
- pub fn apply_style_declaration(&mut self, declaration: &Declaration, origin: Origin) {
- call_inner!(self, apply_style_declaration, declaration, origin)
- }
-
- pub fn set_style_attribute(&mut self, session: &Session) {
- call_inner!(self, set_style_attribute, session);
- }
-
- pub fn as_filter_effect(&self) -> Option<&dyn FilterEffect> {
- match self {
- Element::FeBlend(ref fe) => Some(&fe.element_impl),
- Element::FeColorMatrix(ref fe) => Some(&fe.element_impl),
- Element::FeComponentTransfer(ref fe) => Some(&fe.element_impl),
- Element::FeComposite(ref fe) => Some(&fe.element_impl),
- Element::FeConvolveMatrix(ref fe) => Some(&fe.element_impl),
- Element::FeDiffuseLighting(ref fe) => Some(&fe.element_impl),
- Element::FeDisplacementMap(ref fe) => Some(&fe.element_impl),
- Element::FeDropShadow(ref fe) => Some(&fe.element_impl),
- Element::FeFlood(ref fe) => Some(&fe.element_impl),
- Element::FeGaussianBlur(ref fe) => Some(&fe.element_impl),
- Element::FeImage(ref fe) => Some(&fe.element_impl),
- Element::FeMerge(ref fe) => Some(&fe.element_impl),
- Element::FeMorphology(ref fe) => Some(&fe.element_impl),
- Element::FeOffset(ref fe) => Some(&fe.element_impl),
- Element::FeSpecularLighting(ref fe) => Some(&fe.element_impl),
- Element::FeTile(ref fe) => Some(&fe.element_impl),
- Element::FeTurbulence(ref fe) => Some(&fe.element_impl),
- _ => None,
- }
- }
-
- /// Returns whether an element of a particular type is only accessed by reference
- // from other elements' attributes. The element could in turn cause other nodes
- // to get referenced, potentially causing reference cycles.
- pub fn is_accessed_by_reference(&self) -> bool {
- matches!(
- self,
- Element::ClipPath(_)
- | Element::Filter(_)
- | Element::LinearGradient(_)
- | Element::Marker(_)
- | Element::Mask(_)
- | Element::Pattern(_)
- | Element::RadialGradient(_)
- )
- }
-}
-
-impl ElementTrait for Element {
+impl ElementData {
+ /// Dispatcher for the draw method of concrete element implementations.
+ #[rustfmt::skip]
fn draw(
&self,
node: &Node,
@@ -535,42 +396,75 @@ impl ElementTrait for Element {
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
- call_inner!(
- self,
- draw,
- node,
- acquired_nodes,
- cascaded,
- draw_ctx,
- clipping
- )
- }
-}
+ use ElementData::*;
+
+ let data: &dyn ElementTrait = match self {
+ Circle(d) => &**d,
+ ClipPath(d) => &**d,
+ Ellipse(d) => &**d,
+ Filter(d) => &**d,
+ Group(d) => &**d,
+ Image(d) => &**d,
+ Line(d) => &**d,
+ LinearGradient(d) => &**d,
+ Link(d) => &**d,
+ Marker(d) => &**d,
+ Mask(d) => &**d,
+ NonRendering(d) => &**d,
+ Path(d) => &**d,
+ Pattern(d) => &**d,
+ Polygon(d) => &**d,
+ Polyline(d) => &**d,
+ RadialGradient(d) => &**d,
+ Rect(d) => &**d,
+ Stop(d) => &**d,
+ Style(d) => &**d,
+ Svg(d) => &**d,
+ Switch(d) => &**d,
+ Symbol(d) => &**d,
+ Text(d) => &**d,
+ TRef(d) => &**d,
+ TSpan(d) => &**d,
+ Use(d) => &**d,
+
+ FeBlend(d) => &**d,
+ FeColorMatrix(d) => &**d,
+ FeComponentTransfer(d) => &**d,
+ FeComposite(d) => &**d,
+ FeConvolveMatrix(d) => &**d,
+ FeDiffuseLighting(d) => &**d,
+ FeDisplacementMap(d) => &**d,
+ FeDistantLight(d) => &**d,
+ FeDropShadow(d) => &**d,
+ FeFlood(d) => &**d,
+ FeFuncA(d) => &**d,
+ FeFuncB(d) => &**d,
+ FeFuncG(d) => &**d,
+ FeFuncR(d) => &**d,
+ FeGaussianBlur(d) => &**d,
+ FeImage(d) => &**d,
+ FeMerge(d) => &**d,
+ FeMergeNode(d) => &**d,
+ FeMorphology(d) => &**d,
+ FeOffset(d) => &**d,
+ FePointLight(d) => &**d,
+ FeSpecularLighting(d) => &**d,
+ FeSpotLight(d) => &**d,
+ FeTile(d) => &**d,
+ FeTurbulence(d) => &**d,
+ };
-impl fmt::Display for Element {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- call_inner!(self, fmt, f)
+ data.draw(node, acquired_nodes, cascaded, draw_ctx, clipping)
}
}
macro_rules! e {
($name:ident, $element_type:ident) => {
- pub fn $name(
- session: &Session,
- element_name: &QualName,
- attributes: Attributes,
- ) -> Element {
- let mut element_impl = <$element_type>::default();
- element_impl.set_attributes(&attributes, session);
-
- let element = Element::$element_type(Box::new(ElementInner::new(
- session,
- element_name.clone(),
- attributes,
- element_impl,
- )));
+ pub fn $name(session: &Session, attributes: &Attributes) -> ElementData {
+ let mut payload = Box::new(<$element_type>::default());
+ payload.set_attributes(attributes, session);
- element
+ ElementData::$element_type(payload)
}
};
}
@@ -649,8 +543,7 @@ mod creators {
use creators::*;
-type ElementCreateFn =
- fn(session: &Session, element_name: &QualName, attributes: Attributes) -> Element;
+type ElementDataCreateFn = fn(session: &Session, attributes: &Attributes) -> ElementData;
#[derive(Copy, Clone, PartialEq)]
enum ElementCreateFlags {
@@ -660,10 +553,10 @@ enum ElementCreateFlags {
// Lines in comments are elements that we don't support.
#[rustfmt::skip]
-static ELEMENT_CREATORS: Lazy<HashMap<&'static str, (ElementCreateFn, ElementCreateFlags)>> = Lazy::new(|| {
+static ELEMENT_CREATORS: Lazy<HashMap<&'static str, (ElementDataCreateFn, ElementCreateFlags)>> = Lazy::new(|| {
use ElementCreateFlags::*;
- let creators_table: Vec<(&str, ElementCreateFn, ElementCreateFlags)> = vec![
+ let creators_table: Vec<(&str, ElementDataCreateFn, ElementCreateFlags)> = vec![
// name, supports_class, create_fn
("a", create_link, Default),
/* ("altGlyph", ), */
@@ -753,81 +646,3 @@ static ELEMENT_CREATORS: Lazy<HashMap<&'static str, (ElementCreateFn, ElementCre
creators_table.into_iter().map(|(n, c, f)| (n, (c, f))).collect()
});
-
-#[cfg(ignore)]
-mod sizes {
- //! This module is in this file just because here we have all the imports.
-
- use super::*;
-
- macro_rules! print_size {
- ($ty:ty) => {
- println!("sizeof {}: {}", stringify!($ty), mem::size_of::<$ty>());
- };
- }
-
- pub fn print_sizes() {
- use crate::properties::{ComputedValues, ParsedProperty, SpecifiedValues};
- use std::mem;
-
- print_size!(NodeData);
- print_size!(Element);
- print_size!(SpecifiedValues);
- print_size!(ComputedValues);
- print_size!(ParsedProperty);
-
- print_size!(Circle);
- print_size!(ClipPath);
- print_size!(NonRendering);
- print_size!(Ellipse);
- print_size!(FeBlend);
- print_size!(FeColorMatrix);
- print_size!(FeComponentTransfer);
- print_size!(FeFuncA);
- print_size!(FeFuncB);
- print_size!(FeFuncG);
- print_size!(FeFuncR);
- print_size!(FeComposite);
- print_size!(FeConvolveMatrix);
- print_size!(FeDiffuseLighting);
- print_size!(FeDistantLight);
- print_size!(FeDisplacementMap);
- print_size!(FeDropShadow);
- print_size!(FeFlood);
- print_size!(FeGaussianBlur);
- print_size!(FeImage);
- print_size!(FeMerge);
- print_size!(FeMergeNode);
- print_size!(FeMorphology);
- print_size!(FeOffset);
- print_size!(FePointLight);
- print_size!(FeSpecularLighting);
- print_size!(FeSpotLight);
- print_size!(FeTile);
- print_size!(FeTurbulence);
- print_size!(Filter);
- print_size!(Group);
- print_size!(Image);
- print_size!(Line);
- print_size!(LinearGradient);
- print_size!(Link);
- print_size!(Marker);
- print_size!(Mask);
- print_size!(NonRendering);
- print_size!(Path);
- print_size!(Pattern);
- print_size!(Polygon);
- print_size!(Polyline);
- print_size!(RadialGradient);
- print_size!(Rect);
- print_size!(Stop);
- print_size!(Style);
- print_size!(Svg);
- print_size!(Switch);
- print_size!(Symbol);
- print_size!(Text);
- print_size!(TRef);
- print_size!(TSpan);
- print_size!(Use);
- }
-}
diff --git a/src/filter.rs b/src/filter.rs
index cbe0e038..05aad8ac 100644
--- a/src/filter.rs
+++ b/src/filter.rs
@@ -7,7 +7,7 @@ use std::slice::Iter;
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNodes, NodeId};
use crate::drawing_ctx::{DrawingCtx, ViewParams};
-use crate::element::{set_attribute, Element, ElementTrait};
+use crate::element::{set_attribute, ElementData, ElementTrait};
use crate::error::ValueErrorKind;
use crate::filter_func::FilterFunction;
use crate::filters::{FilterResolveError, FilterSpec};
@@ -242,10 +242,9 @@ fn filter_spec_from_filter_node(
})
.and_then(|acquired| {
let node = acquired.get();
- let element = node.borrow_element();
- match *element {
- Element::Filter(_) => extract_filter_from_filter_node(
+ match *node.borrow_element_data() {
+ ElementData::Filter(_) => extract_filter_from_filter_node(
node,
acquired_nodes,
&session,
diff --git a/src/filters/component_transfer.rs b/src/filters/component_transfer.rs
index c2620622..6f26f683 100644
--- a/src/filters/component_transfer.rs
+++ b/src/filters/component_transfer.rs
@@ -5,7 +5,7 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
-use crate::element::{set_attribute, Element, ElementTrait};
+use crate::element::{set_attribute, ElementData, ElementTrait};
use crate::error::*;
use crate::node::{CascadedValues, Node, NodeBorrow};
use crate::parsers::{NumberList, Parse, ParseValue};
@@ -269,8 +269,8 @@ impl FeFuncCommon {
macro_rules! func_or_default {
($func_node:ident, $func_type:ident) => {
match $func_node {
- Some(ref f) => match *f.borrow_element() {
- Element::$func_type(ref e) => e.element_impl.clone(),
+ Some(ref f) => match &*f.borrow_element_data() {
+ ElementData::$func_type(e) => (**e).clone(),
_ => unreachable!(),
},
_ => $func_type::default(),
@@ -284,7 +284,7 @@ macro_rules! get_func_x_node {
.children()
.rev()
.filter(|c| c.is_element())
- .find(|c| matches!(*c.borrow_element(), Element::$func_type(_)))
+ .find(|c| matches!(*c.borrow_element_data(), ElementData::$func_type(_)))
};
}
diff --git a/src/filters/lighting.rs b/src/filters/lighting.rs
index 0f208d5c..ed39e78b 100644
--- a/src/filters/lighting.rs
+++ b/src/filters/lighting.rs
@@ -9,7 +9,7 @@ use std::cmp::max;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
-use crate::element::{set_attribute, Element, ElementTrait};
+use crate::element::{set_attribute, ElementData, ElementTrait};
use crate::filters::{
bounds::BoundsBuilder,
context::{FilterContext, FilterOutput},
@@ -703,10 +703,10 @@ macro_rules! impl_lighting_filter {
let mut sources = node.children().rev().filter(|c| {
c.is_element()
&& matches!(
- *c.borrow_element(),
- Element::FeDistantLight(_)
- | Element::FePointLight(_)
- | Element::FeSpotLight(_)
+ *c.borrow_element_data(),
+ ElementData::FeDistantLight(_)
+ | ElementData::FePointLight(_)
+ | ElementData::FeSpotLight(_)
)
});
@@ -716,18 +716,13 @@ macro_rules! impl_lighting_filter {
}
let source_node = source_node.unwrap();
- let elt = source_node.borrow_element();
- let source = match *elt {
- Element::FeDistantLight(ref l) => {
- UntransformedLightSource::Distant(l.element_impl.clone())
- }
- Element::FePointLight(ref l) => {
- UntransformedLightSource::Point(l.element_impl.clone())
- }
- Element::FeSpotLight(ref l) => {
- UntransformedLightSource::Spot(l.element_impl.clone())
+ let source = match &*source_node.borrow_element_data() {
+ ElementData::FeDistantLight(l) => {
+ UntransformedLightSource::Distant((**l).clone())
}
+ ElementData::FePointLight(l) => UntransformedLightSource::Point((**l).clone()),
+ ElementData::FeSpotLight(l) => UntransformedLightSource::Spot((**l).clone()),
_ => unreachable!(),
};
diff --git a/src/filters/merge.rs b/src/filters/merge.rs
index 89dc831c..0f762fdd 100644
--- a/src/filters/merge.rs
+++ b/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::element::{set_attribute, Element, ElementTrait};
+use crate::element::{set_attribute, ElementData, ElementTrait};
use crate::node::{CascadedValues, Node, NodeBorrow};
use crate::parsers::ParseValue;
use crate::properties::ColorInterpolationFilters;
@@ -157,14 +157,12 @@ fn resolve_merge_nodes(node: &Node) -> Result<Vec<MergeNode>, FilterResolveError
let mut merge_nodes = Vec::new();
for child in node.children().filter(|c| c.is_element()) {
- let elt = child.borrow_element();
-
let cascaded = CascadedValues::new_from_node(&child);
let values = cascaded.get();
- if let Element::FeMergeNode(ref merge_node) = *elt {
+ if let ElementData::FeMergeNode(merge_node) = &*child.borrow_element_data() {
merge_nodes.push(MergeNode {
- in1: merge_node.element_impl.in1.clone(),
+ in1: merge_node.in1.clone(),
color_interpolation_filters: values.color_interpolation_filters(),
});
}
diff --git a/src/gradient.rs b/src/gradient.rs
index b242d147..1e2d09c5 100644
--- a/src/gradient.rs
+++ b/src/gradient.rs
@@ -8,7 +8,7 @@ use markup5ever::{
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNodes, NodeId, NodeStack};
use crate::drawing_ctx::ViewParams;
-use crate::element::{set_attribute, Element, ElementTrait};
+use crate::element::{set_attribute, ElementData, ElementTrait};
use crate::error::*;
use crate::href::{is_href, set_href};
use crate::length::*;
@@ -408,14 +408,12 @@ impl UnresolvedGradient {
/// and adds their info to the UnresolvedGradient &self.
fn add_color_stops_from_node(&mut self, node: &Node, opacity: UnitInterval) {
assert!(matches!(
- *node.borrow_element(),
- Element::LinearGradient(_) | Element::RadialGradient(_)
+ *node.borrow_element_data(),
+ ElementData::LinearGradient(_) | ElementData::RadialGradient(_)
));
for child in node.children().filter(|c| c.is_element()) {
- let elt = child.borrow_element();
-
- if let Element::Stop(ref stop) = *elt {
+ if let ElementData::Stop(ref stop) = &*child.borrow_element_data() {
let cascaded = CascadedValues::new_from_node(&child);
let values = cascaded.get();
@@ -596,11 +594,11 @@ macro_rules! impl_gradient {
return Err(AcquireError::CircularReference(acquired_node.clone()));
}
- let unresolved = match *acquired_node.borrow_element() {
- Element::$gradient_type(ref g) => {
+ let unresolved = match *acquired_node.borrow_element_data() {
+ ElementData::$gradient_type(ref g) => {
g.get_unresolved(&acquired_node, opacity)
}
- Element::$other_type(ref g) => {
+ ElementData::$other_type(ref g) => {
g.get_unresolved(&acquired_node, opacity)
}
_ => return Err(AcquireError::InvalidLinkType(node_id.clone())),
diff --git a/src/layout.rs b/src/layout.rs
index 7e9cf2c7..19d07baf 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -10,7 +10,7 @@ use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::dasharray::Dasharray;
use crate::document::AcquiredNodes;
-use crate::element::Element;
+use crate::element::{Element, ElementData};
use crate::length::*;
use crate::node::*;
use crate::paint_server::{PaintSource, UserSpacePaintSource};
@@ -148,10 +148,10 @@ impl StackingContext {
let opacity;
let filter;
- match *element {
+ match element.element_data {
// "The opacity, filter and display properties do not apply to the mask element"
// https://drafts.fxtf.org/css-masking-1/#MaskElement
- Element::Mask(_) => {
+ ElementData::Mask(_) => {
opacity = Opacity(UnitInterval::clamp(1.0));
filter = Filter::None;
}
@@ -186,8 +186,8 @@ impl StackingContext {
let mask = values.mask().0.get().and_then(|mask_id| {
if let Ok(acquired) = acquired_nodes.acquire(mask_id) {
let node = acquired.get();
- match *node.borrow_element() {
- Element::Mask(_) => Some(node.clone()),
+ match *node.borrow_element_data() {
+ ElementData::Mask(_) => Some(node.clone()),
_ => {
rsvg_log!(
diff --git a/src/node.rs b/src/node.rs
index f1d4191f..1eab97a0 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -62,17 +62,17 @@ pub type WeakNode = rctree::WeakNode<NodeData>;
/// methods from the `NodeBorrow` trait to see if you can then call
/// `borrow_chars`, `borrow_element`, or `borrow_element_mut`.
pub enum NodeData {
- Element(Element),
- Text(Chars),
+ Element(Box<Element>),
+ Text(Box<Chars>),
}
impl NodeData {
pub fn new_element(session: &Session, name: &QualName, attrs: Attributes) -> NodeData {
- NodeData::Element(Element::new(session, name, attrs))
+ NodeData::Element(Box::new(Element::new(session, name, attrs)))
}
pub fn new_chars(initial_text: &str) -> NodeData {
- NodeData::Text(Chars::new(initial_text))
+ NodeData::Text(Box::new(Chars::new(initial_text)))
}
}
@@ -212,6 +212,11 @@ pub trait NodeBorrow {
///
/// Panics: will panic if `&self` is not a `NodeData::Element` node
fn borrow_element_mut(&mut self) -> RefMut<'_, Element>;
+
+ /// Borrows an `ElementData` reference to the concrete element type.
+ ///
+ /// Panics: will panic if `&self` is not a `NodeData::Element` node
+ fn borrow_element_data(&self) -> Ref<'_, ElementData>;
}
impl NodeBorrow for Node {
@@ -224,33 +229,40 @@ impl NodeBorrow for Node {
}
fn borrow_chars(&self) -> Ref<'_, Chars> {
- Ref::map(self.borrow(), |n| match *n {
- NodeData::Text(ref c) => c,
+ Ref::map(self.borrow(), |n| match n {
+ NodeData::Text(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,
+ Ref::map(self.borrow(), |n| match n {
+ NodeData::Element(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,
+ RefMut::map(self.borrow_mut(), |n| match &mut *n {
+ NodeData::Element(e) => &mut **e,
_ => panic!("tried to borrow_element_mut for a non-element node"),
})
}
+
+ fn borrow_element_data(&self) -> Ref<'_, ElementData> {
+ Ref::map(self.borrow(), |n| match n {
+ NodeData::Element(e) => &e.element_data,
+ _ => panic!("tried to borrow_element_data for a non-element node"),
+ })
+ }
}
#[macro_export]
macro_rules! is_element_of_type {
($node:expr, $element_type:ident) => {
matches!(
- *$node.borrow_element(),
- $crate::element::Element::$element_type(_)
+ $node.borrow_element().element_data,
+ $crate::element::ElementData::$element_type(_)
)
};
}
@@ -258,8 +270,8 @@ macro_rules! is_element_of_type {
#[macro_export]
macro_rules! borrow_element_as {
($node:expr, $element_type:ident) => {
- std::cell::Ref::map($node.borrow_element(), |e| match *e {
- $crate::element::Element::$element_type(ref e) => &*e,
+ std::cell::Ref::map($node.borrow_element_data(), |d| match d {
+ $crate::element::ElementData::$element_type(ref e) => &*e,
_ => panic!("tried to borrow_element_as {}", stringify!($element_type)),
})
};
@@ -287,7 +299,9 @@ impl NodeCascade for Node {
}
}
-/// Helper trait for drawing recursively
+/// Helper trait for drawing recursively.
+///
+/// This is a trait because [`Node`] is a type alias over [`rctree::Node`], not a concrete type.
pub trait NodeDraw {
fn draw(
&self,
diff --git a/src/paint_server.rs b/src/paint_server.rs
index 137435f7..57abd61f 100644
--- a/src/paint_server.rs
+++ b/src/paint_server.rs
@@ -6,7 +6,7 @@ use cssparser::Parser;
use crate::document::{AcquiredNodes, NodeId};
use crate::drawing_ctx::ViewParams;
-use crate::element::Element;
+use crate::element::ElementData;
use crate::error::{AcquireError, NodeIdError, ParseError, ValueErrorKind};
use crate::gradient::{ResolvedGradient, UserSpaceGradient};
use crate::node::NodeBorrow;
@@ -145,8 +145,8 @@ impl PaintServer {
let node = acquired.get();
assert!(node.is_element());
- match *node.borrow_element() {
- Element::LinearGradient(ref g) => {
+ match *node.borrow_element_data() {
+ ElementData::LinearGradient(ref g) => {
g.resolve(node, acquired_nodes, opacity).map(|g| {
Arc::new(PaintSource::Gradient(
g,
@@ -154,7 +154,7 @@ impl PaintServer {
))
})
}
- Element::Pattern(ref p) => {
+ ElementData::Pattern(ref p) => {
p.resolve(node, acquired_nodes, opacity, session).map(|p| {
Arc::new(PaintSource::Pattern(
p,
@@ -162,7 +162,7 @@ impl PaintServer {
))
})
}
- Element::RadialGradient(ref g) => {
+ ElementData::RadialGradient(ref g) => {
g.resolve(node, acquired_nodes, opacity).map(|g| {
Arc::new(PaintSource::Gradient(
g,
diff --git a/src/pattern.rs b/src/pattern.rs
index e7b19755..09df7af2 100644
--- a/src/pattern.rs
+++ b/src/pattern.rs
@@ -6,7 +6,7 @@ use crate::aspect_ratio::*;
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNode, AcquiredNodes, NodeId, NodeStack};
use crate::drawing_ctx::ViewParams;
-use crate::element::{set_attribute, Element, ElementTrait};
+use crate::element::{set_attribute, ElementData, ElementTrait};
use crate::error::*;
use crate::href::{is_href, set_href};
use crate::length::*;
@@ -473,8 +473,8 @@ impl Pattern {
return Err(AcquireError::CircularReference(acquired_node.clone()));
}
- match *acquired_node.borrow_element() {
- Element::Pattern(ref p) => {
+ match *acquired_node.borrow_element_data() {
+ ElementData::Pattern(ref p) => {
let unresolved = p.get_unresolved(acquired_node);
pattern = pattern.resolve_from_fallback(&unresolved.pattern);
fallback = unresolved.fallback;
diff --git a/src/structure.rs b/src/structure.rs
index 88773a41..7fcfb763 100644
--- a/src/structure.rs
+++ b/src/structure.rs
@@ -7,7 +7,7 @@ use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNodes, NodeId};
use crate::drawing_ctx::{ClipMode, DrawingCtx, ViewParams};
-use crate::element::{set_attribute, Element, ElementTrait};
+use crate::element::{set_attribute, ElementData, ElementTrait};
use crate::error::*;
use crate::href::{is_href, set_href};
use crate::layout::StackingContext;
@@ -578,7 +578,7 @@ impl ElementTrait for Link {
// If this element is inside of <text>, do not draw it.
// The <text> takes care of it.
for an in node.ancestors() {
- if matches!(&*an.borrow_element(), Element::Text(_)) {
+ if matches!(&*an.borrow_element_data(), ElementData::Text(_)) {
return Ok(draw_ctx.empty_bbox());
}
}
diff --git a/src/text.rs b/src/text.rs
index 47e87d2b..8505492c 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -10,7 +10,7 @@ use std::sync::Arc;
use crate::bbox::BoundingBox;
use crate::document::{AcquiredNodes, NodeId};
use crate::drawing_ctx::{create_pango_context, DrawingCtx, FontOptions, ViewParams};
-use crate::element::{set_attribute, Element, ElementTrait};
+use crate::element::{set_attribute, ElementData, ElementTrait};
use crate::error::*;
use crate::layout::{self, FontProperties, StackingContext, Stroke, TextSpan};
use crate::length::*;
@@ -537,8 +537,8 @@ fn children_to_chunks(
} else {
assert!(child.is_element());
- match *child.borrow_element() {
- Element::TSpan(ref tspan) => {
+ match *child.borrow_element_data() {
+ ElementData::TSpan(ref tspan) => {
let cascaded = CascadedValues::clone_with_node(cascaded, &child);
tspan.to_chunks(
&child,
@@ -553,7 +553,7 @@ fn children_to_chunks(
);
}
- Element::Link(ref link) => {
+ ElementData::Link(ref link) => {
// TSpan::default sets all offsets to 0,
// which is what we want in links.
//
@@ -577,7 +577,7 @@ fn children_to_chunks(
);
}
- Element::TRef(ref tref) => {
+ ElementData::TRef(ref tref) => {
let cascaded = CascadedValues::clone_with_node(cascaded, &child);
tref.to_chunks(
&child,