[librsvg: 7/10] element: move element code to its own module
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 7/10] element: move element code to its own module
- Date: Mon, 16 Mar 2020 23:43:11 +0000 (UTC)
commit f084dceb1a3bf4936e189085e63cd9aa750bff2c
Author: Paolo Borelli <pborelli gnome org>
Date: Mon Mar 16 11:56:13 2020 +0100
element: move element code to its own module
Move all element code in element.rs, this include the creation
function which is now named create_element.
Makefile.am | 4 +-
po/POTFILES.in | 2 +-
rsvg_internals/src/create_node.rs | 344 ------------
rsvg_internals/src/css.rs | 3 +-
rsvg_internals/src/document.rs | 6 +-
rsvg_internals/src/drawing_ctx.rs | 3 +-
rsvg_internals/src/element.rs | 652 +++++++++++++++++++++++
rsvg_internals/src/filter.rs | 5 +-
rsvg_internals/src/filters/blend.rs | 5 +-
rsvg_internals/src/filters/color_matrix.rs | 5 +-
rsvg_internals/src/filters/component_transfer.rs | 7 +-
rsvg_internals/src/filters/composite.rs | 5 +-
rsvg_internals/src/filters/convolve_matrix.rs | 5 +-
rsvg_internals/src/filters/displacement_map.rs | 5 +-
rsvg_internals/src/filters/flood.rs | 5 +-
rsvg_internals/src/filters/gaussian_blur.rs | 5 +-
rsvg_internals/src/filters/image.rs | 5 +-
rsvg_internals/src/filters/light/light_source.rs | 9 +-
rsvg_internals/src/filters/light/lighting.rs | 9 +-
rsvg_internals/src/filters/merge.rs | 7 +-
rsvg_internals/src/filters/mod.rs | 7 +-
rsvg_internals/src/filters/morphology.rs | 5 +-
rsvg_internals/src/filters/offset.rs | 5 +-
rsvg_internals/src/filters/tile.rs | 5 +-
rsvg_internals/src/filters/turbulence.rs | 5 +-
rsvg_internals/src/gradient.rs | 26 +-
rsvg_internals/src/image.rs | 3 +-
rsvg_internals/src/lib.rs | 2 +-
rsvg_internals/src/marker.rs | 3 +-
rsvg_internals/src/node.rs | 329 +-----------
rsvg_internals/src/pattern.rs | 13 +-
rsvg_internals/src/shapes.rs | 15 +-
rsvg_internals/src/structure.rs | 19 +-
rsvg_internals/src/style.rs | 5 +-
rsvg_internals/src/text.rs | 9 +-
rsvg_internals/src/xml.rs | 3 +-
36 files changed, 786 insertions(+), 759 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 3b3c25d7..e1a92eab 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -29,13 +29,13 @@ LIBRSVG_INTERNALS_SRC = \
rsvg_internals/src/color.rs \
rsvg_internals/src/cond.rs \
rsvg_internals/src/coord_units.rs \
- rsvg_internals/src/create_node.rs \
rsvg_internals/src/css.rs \
- rsvg_internals/src/error.rs \
rsvg_internals/src/dasharray.rs \
rsvg_internals/src/document.rs \
rsvg_internals/src/dpi.rs \
rsvg_internals/src/drawing_ctx.rs \
+ rsvg_internals/src/element.rs \
+ rsvg_internals/src/error.rs \
rsvg_internals/src/filter.rs \
rsvg_internals/src/filters/bounds.rs \
rsvg_internals/src/filters/blend.rs \
diff --git a/po/POTFILES.in b/po/POTFILES.in
index c5591b34..52aefded 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -21,9 +21,9 @@ rsvg_internals/src/bbox.rs
rsvg_internals/src/color.rs
rsvg_internals/src/cond.rs
rsvg_internals/src/coord_units.rs
-rsvg_internals/src/create_node.rs
rsvg_internals/src/css.rs
rsvg_internals/src/drawing_ctx.rs
+rsvg_internals/src/element.rs
rsvg_internals/src/error.rs
rsvg_internals/src/filters/blend.rs
rsvg_internals/src/filters/bounds.rs
diff --git a/rsvg_internals/src/css.rs b/rsvg_internals/src/css.rs
index 4af35e72..e8580e43 100644
--- a/rsvg_internals/src/css.rs
+++ b/rsvg_internals/src/css.rs
@@ -90,9 +90,10 @@ use markup5ever::{namespace_url, ns, LocalName, Namespace, Prefix, QualName};
use url::Url;
use crate::allowed_url::AllowedUrl;
+use crate::element::ElementType;
use crate::error::*;
use crate::io::{self, BinaryData};
-use crate::node::{ElementType, NodeBorrow, NodeCascade, RsvgNode};
+use crate::node::{NodeBorrow, NodeCascade, RsvgNode};
use crate::properties::{parse_property, ComputedValues, ParsedProperty};
/// A parsed CSS declaration
diff --git a/rsvg_internals/src/document.rs b/rsvg_internals/src/document.rs
index 018eb0bd..18210469 100644
--- a/rsvg_internals/src/document.rs
+++ b/rsvg_internals/src/document.rs
@@ -8,13 +8,13 @@ use std::collections::HashMap;
use std::rc::Rc;
use crate::allowed_url::{AllowedUrl, AllowedUrlError, Fragment};
-use crate::create_node::create_node;
use crate::css::{self, Origin, Stylesheet};
+use crate::element::ElementType;
use crate::error::{AcquireError, LoadingError};
use crate::handle::LoadOptions;
use crate::io::{self, BinaryData};
use crate::limits;
-use crate::node::{ElementType, NodeBorrow, NodeData, RsvgNode};
+use crate::node::{NodeBorrow, NodeData, RsvgNode};
use crate::property_bag::PropertyBag;
use crate::structure::{IntrinsicDimensions, Svg};
use crate::surface_utils::shared_surface::SharedImageSurface;
@@ -438,7 +438,7 @@ impl DocumentBuilder {
pbag: &PropertyBag,
parent: Option<RsvgNode>,
) -> RsvgNode {
- let mut node = create_node(name, pbag);
+ let mut node = RsvgNode::new(NodeData::new_element(name, pbag));
if let Some(id) = node.borrow_element().get_id() {
// This is so we don't overwrite an existing id
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index 126f1c8b..2620dbfd 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -14,11 +14,12 @@ use crate::coord_units::CoordUnits;
use crate::dasharray::Dasharray;
use crate::document::{AcquiredNode, AcquiredNodes};
use crate::dpi::Dpi;
+use crate::element::ElementType;
use crate::error::{AcquireError, RenderingError};
use crate::filters;
use crate::gradient::{LinearGradient, RadialGradient};
use crate::marker;
-use crate::node::{CascadedValues, ElementType, NodeBorrow, NodeDraw, RsvgNode};
+use crate::node::{CascadedValues, NodeBorrow, NodeDraw, RsvgNode};
use crate::paint_server::{PaintServer, PaintSource};
use crate::path_builder::*;
use crate::pattern::Pattern;
diff --git a/rsvg_internals/src/element.rs b/rsvg_internals/src/element.rs
new file mode 100644
index 00000000..0ed9b165
--- /dev/null
+++ b/rsvg_internals/src/element.rs
@@ -0,0 +1,652 @@
+//! SVG Elements.
+//!
+//! The [`create_element`] function takes an XML element name, and
+//! creates an [`Element`] for it.
+//!
+//! [`create_element`]: fn.create_element.html
+
+use locale_config::Locale;
+use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
+use once_cell::sync::Lazy;
+use std::collections::{HashMap, HashSet};
+use std::fmt;
+
+use crate::cond::{RequiredExtensions, RequiredFeatures, SystemLanguage};
+use crate::css::Declaration;
+use crate::error::*;
+use crate::filter::Filter;
+use crate::filters::{
+ blend::FeBlend,
+ color_matrix::FeColorMatrix,
+ component_transfer::{FeComponentTransfer, FeFuncA, FeFuncB, FeFuncG, FeFuncR},
+ composite::FeComposite,
+ convolve_matrix::FeConvolveMatrix,
+ displacement_map::FeDisplacementMap,
+ flood::FeFlood,
+ gaussian_blur::FeGaussianBlur,
+ image::FeImage,
+ light::{
+ light_source::FeDistantLight, light_source::FePointLight, light_source::FeSpotLight,
+ lighting::FeDiffuseLighting, lighting::FeSpecularLighting,
+ },
+ merge::{FeMerge, FeMergeNode},
+ morphology::FeMorphology,
+ offset::FeOffset,
+ tile::FeTile,
+ turbulence::FeTurbulence,
+};
+use crate::gradient::{LinearGradient, RadialGradient, Stop};
+use crate::image::Image;
+use crate::marker::Marker;
+use crate::node::*;
+use crate::parsers::Parse;
+use crate::pattern::Pattern;
+use crate::properties::{ComputedValues, SpecifiedValue, SpecifiedValues};
+use crate::property_bag::PropertyBag;
+use crate::property_defs::Overflow;
+use crate::shapes::{Circle, Ellipse, Line, Path, Polygon, Polyline, Rect};
+use crate::structure::{ClipPath, Group, Link, Mask, NonRendering, Svg, Switch, Symbol, Use};
+use crate::style::Style;
+use crate::text::{TRef, TSpan, Text};
+use crate::transform::Transform;
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
+pub enum ElementType {
+ Circle,
+ ClipPath,
+ Ellipse,
+ Filter,
+ Group,
+ Image,
+ Line,
+ LinearGradient,
+ Link,
+ Marker,
+ Mask,
+ NonRendering,
+ Path,
+ Pattern,
+ Polygon,
+ Polyline,
+ RadialGradient,
+ Rect,
+ Stop,
+ Style,
+ Svg,
+ Switch,
+ Symbol,
+ Text,
+ TRef,
+ TSpan,
+ Use,
+
+ // Filter primitives, these start with "Fe" as element names are e.g. "feBlend"
+ FeBlend,
+ FeColorMatrix,
+ FeComponentTransfer,
+ FeComposite,
+ FeConvolveMatrix,
+ FeDiffuseLighting,
+ FeDisplacementMap,
+ FeDistantLight,
+ FeFlood,
+ FeFuncA,
+ FeFuncB,
+ FeFuncG,
+ FeFuncR,
+ FeGaussianBlur,
+ FeImage,
+ FeMerge,
+ FeMergeNode,
+ FeMorphology,
+ FeOffset,
+ FePointLight,
+ FeSpecularLighting,
+ FeSpotLight,
+ FeTile,
+ FeTurbulence,
+}
+
+// After creating/parsing a Element, it will be in a success or an error state.
+// We represent this with a Result, aliased as a ElementResult. There is no
+// extra information for the Ok case; all the interesting stuff is in the
+// Err case.
+//
+// https://www.w3.org/TR/SVG/implnote.html#ErrorProcessing
+//
+// When an element has an error during parsing, the SVG spec calls the element
+// to be "in error". We skip rendering of elements that are in error.
+//
+// When we parse an element's attributes, we stop as soon as we
+// encounter the first error: a parse error, or an invalid value,
+// etc. No further attributes will be processed, although note that
+// the order in which an element's attributes are processed is not
+// defined.
+//
+// Alternatively, we could try to parse/validate all the attributes
+// that come in an element and build up a Vec<ElementError>. However, we
+// don't do this now. Doing that may be more useful for an SVG
+// validator, not a renderer like librsvg is.
+pub type ElementResult = Result<(), NodeError>;
+
+/// Contents of an element node in the DOM
+pub struct Element {
+ element_type: ElementType,
+ element_name: QualName,
+ id: Option<String>, // id attribute from XML element
+ class: Option<String>, // class attribute from XML element
+ specified_values: SpecifiedValues,
+ important_styles: HashSet<QualName>,
+ result: ElementResult,
+ transform: Transform,
+ values: ComputedValues,
+ cond: bool,
+ style_attr: String,
+ node_impl: Box<dyn NodeTrait>,
+}
+
+impl Element {
+ pub fn get_type(&self) -> ElementType {
+ self.element_type
+ }
+
+ pub fn get_node_trait(&self) -> &dyn NodeTrait {
+ self.node_impl.as_ref()
+ }
+
+ pub fn get_impl<T: NodeTrait>(&self) -> &T {
+ if let Some(t) = (&self.node_impl).downcast_ref::<T>() {
+ t
+ } else {
+ panic!("could not downcast");
+ }
+ }
+
+ pub fn element_name(&self) -> &QualName {
+ &self.element_name
+ }
+
+ pub fn get_id(&self) -> Option<&str> {
+ self.id.as_ref().map(String::as_str)
+ }
+
+ pub fn get_class(&self) -> Option<&str> {
+ self.class.as_ref().map(String::as_str)
+ }
+
+ pub fn get_specified_values(&self) -> &SpecifiedValues {
+ &self.specified_values
+ }
+
+ pub fn get_computed_values(&self) -> &ComputedValues {
+ &self.values
+ }
+
+ pub fn set_computed_values(&mut self, values: &ComputedValues) {
+ self.values = values.clone();
+ }
+
+ pub fn get_cond(&self) -> bool {
+ self.cond
+ }
+
+ pub fn get_transform(&self) -> Transform {
+ self.transform
+ }
+
+ pub fn is_overflow(&self) -> bool {
+ self.specified_values.is_overflow()
+ }
+
+ pub fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>, locale: &Locale) {
+ if self.node_impl.overflow_hidden() {
+ self.specified_values.overflow = SpecifiedValue::Specified(Overflow::Hidden);
+ }
+
+ self.save_style_attribute(pbag);
+
+ if let Err(e) = self
+ .set_transform_attribute(pbag)
+ .and_then(|_| self.set_conditional_processing_attributes(pbag, locale))
+ .and_then(|_| self.node_impl.set_atts(parent, pbag))
+ .and_then(|_| self.set_presentation_attributes(pbag))
+ {
+ self.set_error(e);
+ }
+
+ self.node_impl
+ .set_overridden_properties(&mut self.specified_values);
+ }
+
+ fn save_style_attribute(&mut self, pbag: &PropertyBag<'_>) {
+ for (attr, value) in pbag.iter() {
+ match attr.expanded() {
+ expanded_name!("", "style") => self.style_attr.push_str(value),
+ _ => (),
+ }
+ }
+ }
+
+ fn set_transform_attribute(&mut self, pbag: &PropertyBag<'_>) -> Result<(), NodeError> {
+ for (attr, value) in pbag.iter() {
+ match attr.expanded() {
+ expanded_name!("", "transform") => {
+ return Transform::parse_str(value)
+ .attribute(attr)
+ .and_then(|affine| {
+ self.transform = affine;
+ Ok(())
+ });
+ }
+ _ => (),
+ }
+ }
+
+ Ok(())
+ }
+
+ fn set_conditional_processing_attributes(
+ &mut self,
+ pbag: &PropertyBag<'_>,
+ locale: &Locale,
+ ) -> Result<(), NodeError> {
+ let mut cond = self.cond;
+
+ for (attr, value) in pbag.iter() {
+ let mut parse = || -> Result<_, ValueErrorKind> {
+ match attr.expanded() {
+ expanded_name!("", "requiredExtensions") if cond => {
+ cond = RequiredExtensions::from_attribute(value)
+ .map(|RequiredExtensions(res)| res)?;
+ }
+
+ expanded_name!("", "requiredFeatures") if cond => {
+ cond = RequiredFeatures::from_attribute(value)
+ .map(|RequiredFeatures(res)| res)?;
+ }
+
+ expanded_name!("", "systemLanguage") if cond => {
+ cond = SystemLanguage::from_attribute(value, locale)
+ .map(|SystemLanguage(res)| res)?;
+ }
+
+ _ => {}
+ }
+
+ Ok(cond)
+ };
+
+ parse().map(|c| self.cond = c).attribute(attr)?;
+ }
+
+ Ok(())
+ }
+
+ /// Hands the pbag to the node's state, to apply the presentation attributes
+ fn set_presentation_attributes(&mut self, pbag: &PropertyBag<'_>) -> Result<(), NodeError> {
+ match self.specified_values.parse_presentation_attributes(pbag) {
+ Ok(_) => Ok(()),
+ Err(e) => {
+ // FIXME: we'll ignore errors here for now.
+ //
+ // If we set the node to be in error, we expose buggy handling of the
+ // enable-background property; we are not parsing it correctly. This
+ // causes tests/fixtures/reftests/bugs/587721-text-transform.svg to fail
+ // because it has enable-background="new 0 0 1179.75118 687.74173" in the
+ // toplevel svg element.
+ //
+ // self.set_error(e);
+ // return;
+
+ rsvg_log!("(attribute error: {})", e);
+ Ok(())
+ }
+ }
+ }
+
+ // Applies a style declaration to the node's specified_values
+ pub fn apply_style_declaration(&mut self, declaration: &Declaration) {
+ self.specified_values
+ .set_property_from_declaration(declaration, &mut self.important_styles);
+ }
+
+ /// Applies CSS styles from the saved value of the "style" attribute
+ pub fn set_style_attribute(&mut self) {
+ if !self.style_attr.is_empty() {
+ if let Err(e) = self
+ .specified_values
+ .parse_style_declarations(self.style_attr.as_str(), &mut self.important_styles)
+ {
+ self.set_error(e);
+ }
+
+ self.style_attr.clear();
+ self.style_attr.shrink_to_fit();
+ }
+ }
+
+ fn set_error(&mut self, error: NodeError) {
+ rsvg_log!("setting node {} in error: {}", self, error);
+ self.result = Err(error);
+ }
+
+ pub fn is_in_error(&self) -> bool {
+ self.result.is_err()
+ }
+}
+
+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(())
+ }
+}
+
+macro_rules! e {
+ ($name:ident, $element_type:ident) => {
+ pub fn $name(element_name: &QualName, id: Option<&str>, class: Option<&str>) -> Element {
+ Element {
+ element_type: ElementType::$element_type,
+ element_name: element_name.clone(),
+ id: id.map(str::to_string),
+ class: class.map(str::to_string),
+ specified_values: Default::default(),
+ important_styles: Default::default(),
+ transform: Default::default(),
+ result: Ok(()),
+ values: ComputedValues::default(),
+ cond: true,
+ style_attr: String::new(),
+ node_impl: Box::new(<$element_type>::default()),
+ }
+ }
+ };
+}
+
+#[rustfmt::skip]
+mod creators {
+ use super::*;
+
+ e!(create_circle, Circle);
+ e!(create_clip_path, ClipPath);
+ e!(create_defs, NonRendering);
+ e!(create_ellipse, Ellipse);
+ e!(create_fe_blend, FeBlend);
+ e!(create_fe_color_matrix, FeColorMatrix);
+ e!(create_fe_component_transfer, FeComponentTransfer);
+ e!(create_fe_func_a, FeFuncA);
+ e!(create_fe_func_b, FeFuncB);
+ e!(create_fe_func_g, FeFuncG);
+ e!(create_fe_func_r, FeFuncR);
+ e!(create_fe_composite, FeComposite);
+ e!(create_fe_convolve_matrix, FeConvolveMatrix);
+ e!(create_fe_diffuse_lighting, FeDiffuseLighting);
+ e!(create_fe_distant_light, FeDistantLight);
+ e!(create_fe_displacement_map, FeDisplacementMap);
+ e!(create_fe_flood, FeFlood);
+ e!(create_fe_gaussian_blur, FeGaussianBlur);
+ e!(create_fe_image, FeImage);
+ e!(create_fe_merge, FeMerge);
+ e!(create_fe_merge_node, FeMergeNode);
+ e!(create_fe_morphology, FeMorphology);
+ e!(create_fe_offset, FeOffset);
+ e!(create_fe_point_light, FePointLight);
+ e!(create_fe_specular_lighting, FeSpecularLighting);
+ e!(create_fe_spot_light, FeSpotLight);
+ e!(create_fe_tile, FeTile);
+ e!(create_fe_turbulence, FeTurbulence);
+ e!(create_filter, Filter);
+ e!(create_group, Group);
+ e!(create_image, Image);
+ e!(create_line, Line);
+ e!(create_linear_gradient, LinearGradient);
+ e!(create_link, Link);
+ e!(create_marker, Marker);
+ e!(create_mask, Mask);
+ e!(create_non_rendering, NonRendering);
+ e!(create_path, Path);
+ e!(create_pattern, Pattern);
+ e!(create_polygon, Polygon);
+ e!(create_polyline, Polyline);
+ e!(create_radial_gradient, RadialGradient);
+ e!(create_rect, Rect);
+ e!(create_stop, Stop);
+ e!(create_style, Style);
+ e!(create_svg, Svg);
+ e!(create_switch, Switch);
+ e!(create_symbol, Symbol);
+ e!(create_text, Text);
+ e!(create_tref, TRef);
+ e!(create_tspan, TSpan);
+ e!(create_use, Use);
+
+ /* Hack to make multiImage sort-of work
+ *
+ * disabled for now, as markup5ever doesn't have local names for
+ * multiImage, subImage, subImageRef. Maybe we can just... create them ourselves?
+ *
+ * Is multiImage even in SVG2?
+ */
+ /*
+ e!(create_multi_image, Switch);
+ e!(create_sub_image, Group);
+ e!(create_sub_image_ref, Image);
+ */
+}
+
+use creators::*;
+
+type ElementCreateFn =
+ fn(element_name: &QualName, id: Option<&str>, class: Option<&str>) -> Element;
+
+// Lines in comments are elements that we don't support.
+#[rustfmt::skip]
+static ELEMENT_CREATORS: Lazy<HashMap<&'static str, (bool, ElementCreateFn)>> = Lazy::new(|| {
+ let creators_table: Vec<(&str, bool, ElementCreateFn)> = vec![
+ // name, supports_class, create_fn
+ ("a", true, create_link),
+ /* ("altGlyph", true, ), */
+ /* ("altGlyphDef", false, ), */
+ /* ("altGlyphItem", false, ), */
+ /* ("animate", false, ), */
+ /* ("animateColor", false, ), */
+ /* ("animateMotion", false, ), */
+ /* ("animateTransform", false, ), */
+ ("circle", true, create_circle),
+ ("clipPath", true, create_clip_path),
+ /* ("color-profile", false, ), */
+ /* ("cursor", false, ), */
+ ("defs", true, create_defs),
+ /* ("desc", true, ), */
+ ("ellipse", true, create_ellipse),
+ ("feBlend", true, create_fe_blend),
+ ("feColorMatrix", true, create_fe_color_matrix),
+ ("feComponentTransfer", true, create_fe_component_transfer),
+ ("feComposite", true, create_fe_composite),
+ ("feConvolveMatrix", true, create_fe_convolve_matrix),
+ ("feDiffuseLighting", true, create_fe_diffuse_lighting),
+ ("feDisplacementMap", true, create_fe_displacement_map),
+ ("feDistantLight", false, create_fe_distant_light),
+ ("feFuncA", false, create_fe_func_a),
+ ("feFuncB", false, create_fe_func_b),
+ ("feFuncG", false, create_fe_func_g),
+ ("feFuncR", false, create_fe_func_r),
+ ("feFlood", true, create_fe_flood),
+ ("feGaussianBlur", true, create_fe_gaussian_blur),
+ ("feImage", true, create_fe_image),
+ ("feMerge", true, create_fe_merge),
+ ("feMergeNode", false, create_fe_merge_node),
+ ("feMorphology", true, create_fe_morphology),
+ ("feOffset", true, create_fe_offset),
+ ("fePointLight", false, create_fe_point_light),
+ ("feSpecularLighting", true, create_fe_specular_lighting),
+ ("feSpotLight", false, create_fe_spot_light),
+ ("feTile", true, create_fe_tile),
+ ("feTurbulence", true, create_fe_turbulence),
+ ("filter", true, create_filter),
+ /* ("font", true, ), */
+ /* ("font-face", false, ), */
+ /* ("font-face-format", false, ), */
+ /* ("font-face-name", false, ), */
+ /* ("font-face-src", false, ), */
+ /* ("font-face-uri", false, ), */
+ /* ("foreignObject", true, ), */
+ ("g", true, create_group),
+ /* ("glyph", true, ), */
+ /* ("glyphRef", true, ), */
+ /* ("hkern", false, ), */
+ ("image", true, create_image),
+ ("line", true, create_line),
+ ("linearGradient", true, create_linear_gradient),
+ ("marker", true, create_marker),
+ ("mask", true, create_mask),
+ /* ("metadata", false, ), */
+ /* ("missing-glyph", true, ), */
+ /* ("mpath", false, ), */
+ /* ("multiImage", false, create_multi_image), */
+ ("path", true, create_path),
+ ("pattern", true, create_pattern),
+ ("polygon", true, create_polygon),
+ ("polyline", true, create_polyline),
+ ("radialGradient", true, create_radial_gradient),
+ ("rect", true, create_rect),
+ /* ("script", false, ), */
+ /* ("set", false, ), */
+ ("stop", true, create_stop),
+ ("style", false, create_style),
+ /* ("subImage", false, create_sub_image), */
+ /* ("subImageRef", false, create_sub_image_ref), */
+ ("svg", true, create_svg),
+ ("switch", true, create_switch),
+ ("symbol", true, create_symbol),
+ ("text", true, create_text),
+ /* ("textPath", true, ), */
+ /* ("title", true, ), */
+ ("tref", true, create_tref),
+ ("tspan", true, create_tspan),
+ ("use", true, create_use),
+ /* ("view", false, ), */
+ /* ("vkern", false, ), */
+ ];
+
+ creators_table.into_iter().map(|(n, s, f)| (n, (s, f))).collect()
+});
+
+/// Takes an XML element name and a list of attribute/value pairs and creates an [`Element`].
+///
+/// This operation does not fail. Unknown element names simply produce a [`NonRendering`]
+/// element.
+///
+/// [`Element`]: type.Element.html
+/// [`NonRendering`]: ../structure/struct.NonRendering.html
+pub fn create_element(name: &QualName, pbag: &PropertyBag) -> Element {
+ let mut id = None;
+ let mut class = None;
+
+ for (attr, value) in pbag.iter() {
+ match attr.expanded() {
+ expanded_name!("", "id") => id = Some(value),
+ expanded_name!("", "class") => class = Some(value),
+ _ => (),
+ }
+ }
+
+ let (supports_class, create_fn) = if name.ns == ns!(svg) {
+ match ELEMENT_CREATORS.get(name.local.as_ref()) {
+ // hack in the SVG namespace for supported element names
+ Some(&(supports_class, create_fn)) => (supports_class, create_fn),
+
+ // 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 => (true, create_non_rendering as ElementCreateFn),
+ }
+ } else {
+ (true, create_non_rendering as ElementCreateFn)
+ };
+
+ if !supports_class {
+ class = None;
+ };
+
+ // sizes::print_sizes();
+
+ create_fn(name, id, class)
+}
+
+#[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!(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!(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/rsvg_internals/src/filter.rs b/rsvg_internals/src/filter.rs
index 10c692b0..b55a0f7f 100644
--- a/rsvg_internals/src/filter.rs
+++ b/rsvg_internals/src/filter.rs
@@ -5,9 +5,10 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::ElementResult;
use crate::error::ValueErrorKind;
use crate::length::*;
-use crate::node::{NodeResult, NodeTrait, RsvgNode};
+use crate::node::{NodeTrait, RsvgNode};
use crate::parsers::{Parse, ParseValue};
use crate::properties::ComputedValues;
use crate::property_bag::PropertyBag;
@@ -111,7 +112,7 @@ impl Filter {
}
impl NodeTrait for Filter {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
// Parse filterUnits first as it affects x, y, width, height checks.
for (attr, value) in pbag.iter() {
match attr.expanded() {
diff --git a/rsvg_internals/src/filters/blend.rs b/rsvg_internals/src/filters/blend.rs
index 9c75522f..2d6dd16a 100755
--- a/rsvg_internals/src/filters/blend.rs
+++ b/rsvg_internals/src/filters/blend.rs
@@ -3,8 +3,9 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::ElementResult;
use crate::error::*;
-use crate::node::{NodeResult, NodeTrait, RsvgNode};
+use crate::node::{NodeTrait, RsvgNode};
use crate::parsers::{Parse, ParseValue};
use crate::property_bag::PropertyBag;
@@ -55,7 +56,7 @@ impl Default for FeBlend {
impl NodeTrait for FeBlend {
impl_node_as_filter_effect!();
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
diff --git a/rsvg_internals/src/filters/color_matrix.rs b/rsvg_internals/src/filters/color_matrix.rs
index 7a1dd186..e1e12416 100644
--- a/rsvg_internals/src/filters/color_matrix.rs
+++ b/rsvg_internals/src/filters/color_matrix.rs
@@ -4,8 +4,9 @@ use nalgebra::{Matrix3, Matrix4x5, Matrix5, Vector5};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::ElementResult;
use crate::error::*;
-use crate::node::{NodeResult, NodeTrait, RsvgNode};
+use crate::node::{NodeTrait, RsvgNode};
use crate::number_list::{NumberList, NumberListLength};
use crate::parsers::{Parse, ParseValue};
use crate::property_bag::PropertyBag;
@@ -53,7 +54,7 @@ impl Default for FeColorMatrix {
impl NodeTrait for FeColorMatrix {
impl_node_as_filter_effect!();
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)?;
// First, determine the operation type.
diff --git a/rsvg_internals/src/filters/component_transfer.rs
b/rsvg_internals/src/filters/component_transfer.rs
index f0848657..5fc339e4 100644
--- a/rsvg_internals/src/filters/component_transfer.rs
+++ b/rsvg_internals/src/filters/component_transfer.rs
@@ -5,8 +5,9 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::{ElementResult, ElementType};
use crate::error::*;
-use crate::node::{ElementType, NodeBorrow, NodeResult, NodeTrait, RsvgNode};
+use crate::node::{NodeBorrow, NodeTrait, RsvgNode};
use crate::number_list::{NumberList, NumberListLength};
use crate::parsers::{Parse, ParseValue};
use crate::property_bag::PropertyBag;
@@ -37,7 +38,7 @@ impl NodeTrait for FeComponentTransfer {
impl_node_as_filter_effect!();
#[inline]
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)
}
}
@@ -204,7 +205,7 @@ macro_rules! func_x {
&mut self,
_parent: Option<&RsvgNode>,
pbag: &PropertyBag<'_>,
- ) -> NodeResult {
+ ) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "type") => self.function_type = attr.parse(value)?,
diff --git a/rsvg_internals/src/filters/composite.rs b/rsvg_internals/src/filters/composite.rs
index 277bf3aa..2d6225d0 100644
--- a/rsvg_internals/src/filters/composite.rs
+++ b/rsvg_internals/src/filters/composite.rs
@@ -3,8 +3,9 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::ElementResult;
use crate::error::*;
-use crate::node::{NodeResult, NodeTrait, RsvgNode};
+use crate::node::{NodeTrait, RsvgNode};
use crate::parsers::{Parse, ParseValue};
use crate::property_bag::PropertyBag;
@@ -53,7 +54,7 @@ impl Default for FeComposite {
impl NodeTrait for FeComposite {
impl_node_as_filter_effect!();
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
diff --git a/rsvg_internals/src/filters/convolve_matrix.rs b/rsvg_internals/src/filters/convolve_matrix.rs
index f0dc251f..abe0ebe7 100644
--- a/rsvg_internals/src/filters/convolve_matrix.rs
+++ b/rsvg_internals/src/filters/convolve_matrix.rs
@@ -4,8 +4,9 @@ use nalgebra::{DMatrix, Dynamic, VecStorage};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::ElementResult;
use crate::error::*;
-use crate::node::{NodeResult, NodeTrait, RsvgNode};
+use crate::node::{NodeTrait, RsvgNode};
use crate::number_list::{NumberList, NumberListLength};
use crate::parsers::{NumberOptionalNumber, Parse, ParseValue};
use crate::property_bag::PropertyBag;
@@ -56,7 +57,7 @@ impl Default for FeConvolveMatrix {
impl NodeTrait for FeConvolveMatrix {
impl_node_as_filter_effect!();
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
diff --git a/rsvg_internals/src/filters/displacement_map.rs b/rsvg_internals/src/filters/displacement_map.rs
index 86776bc7..7add536f 100644
--- a/rsvg_internals/src/filters/displacement_map.rs
+++ b/rsvg_internals/src/filters/displacement_map.rs
@@ -3,8 +3,9 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::ElementResult;
use crate::error::*;
-use crate::node::{NodeResult, NodeTrait, RsvgNode};
+use crate::node::{NodeTrait, RsvgNode};
use crate::parsers::{Parse, ParseValue};
use crate::property_bag::PropertyBag;
use crate::surface_utils::{iterators::Pixels, shared_surface::ExclusiveImageSurface};
@@ -47,7 +48,7 @@ impl Default for FeDisplacementMap {
impl NodeTrait for FeDisplacementMap {
impl_node_as_filter_effect!();
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
diff --git a/rsvg_internals/src/filters/flood.rs b/rsvg_internals/src/filters/flood.rs
index 9886a308..34253602 100644
--- a/rsvg_internals/src/filters/flood.rs
+++ b/rsvg_internals/src/filters/flood.rs
@@ -1,6 +1,7 @@
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
-use crate::node::{CascadedValues, NodeResult, NodeTrait, RsvgNode};
+use crate::element::ElementResult;
+use crate::node::{CascadedValues, NodeTrait, RsvgNode};
use crate::property_bag::PropertyBag;
use super::context::{FilterContext, FilterOutput, FilterResult};
@@ -25,7 +26,7 @@ impl NodeTrait for FeFlood {
impl_node_as_filter_effect!();
#[inline]
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)
}
}
diff --git a/rsvg_internals/src/filters/gaussian_blur.rs b/rsvg_internals/src/filters/gaussian_blur.rs
index 813c6bd9..201dfccf 100644
--- a/rsvg_internals/src/filters/gaussian_blur.rs
+++ b/rsvg_internals/src/filters/gaussian_blur.rs
@@ -6,8 +6,9 @@ use nalgebra::{DMatrix, Dynamic, VecStorage};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::ElementResult;
use crate::error::*;
-use crate::node::{NodeResult, NodeTrait, RsvgNode};
+use crate::node::{NodeTrait, RsvgNode};
use crate::parsers::{NumberOptionalNumber, ParseValue};
use crate::property_bag::PropertyBag;
use crate::rect::IRect;
@@ -44,7 +45,7 @@ impl Default for FeGaussianBlur {
impl NodeTrait for FeGaussianBlur {
impl_node_as_filter_effect!();
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
diff --git a/rsvg_internals/src/filters/image.rs b/rsvg_internals/src/filters/image.rs
index bf9a7844..f53aa7b3 100644
--- a/rsvg_internals/src/filters/image.rs
+++ b/rsvg_internals/src/filters/image.rs
@@ -4,8 +4,9 @@ use crate::allowed_url::{Fragment, Href};
use crate::aspect_ratio::AspectRatio;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::ElementResult;
use crate::error::*;
-use crate::node::{CascadedValues, NodeResult, NodeTrait, RsvgNode};
+use crate::node::{CascadedValues, NodeTrait, RsvgNode};
use crate::parsers::ParseValue;
use crate::property_bag::PropertyBag;
use crate::rect::Rect;
@@ -112,7 +113,7 @@ impl FeImage {
impl NodeTrait for FeImage {
impl_node_as_filter_effect!();
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
diff --git a/rsvg_internals/src/filters/light/light_source.rs
b/rsvg_internals/src/filters/light/light_source.rs
index c390e2c3..61dc1f37 100644
--- a/rsvg_internals/src/filters/light/light_source.rs
+++ b/rsvg_internals/src/filters/light/light_source.rs
@@ -2,8 +2,9 @@ use cssparser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};
use nalgebra::Vector3;
+use crate::element::ElementResult;
use crate::filters::context::FilterContext;
-use crate::node::{NodeResult, NodeTrait, RsvgNode};
+use crate::node::{NodeTrait, RsvgNode};
use crate::parsers::ParseValue;
use crate::property_bag::PropertyBag;
use crate::util::clamp;
@@ -103,7 +104,7 @@ impl FeDistantLight {
}
impl NodeTrait for FeDistantLight {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "azimuth") => self.azimuth = attr.parse(value)?,
@@ -135,7 +136,7 @@ impl FePointLight {
}
impl NodeTrait for FePointLight {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "x") => self.x = attr.parse(value)?,
@@ -184,7 +185,7 @@ impl FeSpotLight {
}
impl NodeTrait for FeSpotLight {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "x") => self.x = attr.parse(value)?,
diff --git a/rsvg_internals/src/filters/light/lighting.rs b/rsvg_internals/src/filters/light/lighting.rs
index 071d0067..283029fb 100644
--- a/rsvg_internals/src/filters/light/lighting.rs
+++ b/rsvg_internals/src/filters/light/lighting.rs
@@ -7,6 +7,7 @@ use rayon::prelude::*;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::{ElementResult, ElementType};
use crate::error::*;
use crate::filters::{
context::{FilterContext, FilterOutput, FilterResult},
@@ -18,7 +19,7 @@ use crate::filters::{
},
FilterEffect, FilterError, PrimitiveWithInput,
};
-use crate::node::{CascadedValues, ElementType, NodeBorrow, NodeResult, NodeTrait, RsvgNode};
+use crate::node::{CascadedValues, NodeBorrow, NodeTrait, RsvgNode};
use crate::parsers::{NumberOptionalNumber, ParseValue};
use crate::property_bag::PropertyBag;
use crate::surface_utils::{
@@ -48,7 +49,7 @@ impl Common {
}
}
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
@@ -95,7 +96,7 @@ impl Default for FeDiffuseLighting {
impl NodeTrait for FeDiffuseLighting {
impl_node_as_filter_effect!();
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.common.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
@@ -164,7 +165,7 @@ impl Default for FeSpecularLighting {
impl NodeTrait for FeSpecularLighting {
impl_node_as_filter_effect!();
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.common.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
diff --git a/rsvg_internals/src/filters/merge.rs b/rsvg_internals/src/filters/merge.rs
index d1949bd3..4c7cb34b 100644
--- a/rsvg_internals/src/filters/merge.rs
+++ b/rsvg_internals/src/filters/merge.rs
@@ -2,7 +2,8 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
-use crate::node::{ElementType, NodeBorrow, NodeResult, NodeTrait, RsvgNode};
+use crate::element::{ElementResult, ElementType};
+use crate::node::{NodeBorrow, NodeTrait, RsvgNode};
use crate::parsers::ParseValue;
use crate::property_bag::PropertyBag;
use crate::rect::IRect;
@@ -37,14 +38,14 @@ impl NodeTrait for FeMerge {
impl_node_as_filter_effect!();
#[inline]
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)
}
}
impl NodeTrait for FeMergeNode {
#[inline]
- fn set_atts(&mut self, _parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "in") => self.in_ = Some(attr.parse(value)?),
diff --git a/rsvg_internals/src/filters/mod.rs b/rsvg_internals/src/filters/mod.rs
index 61d93fa6..ca5e8f37 100644
--- a/rsvg_internals/src/filters/mod.rs
+++ b/rsvg_internals/src/filters/mod.rs
@@ -9,10 +9,11 @@ use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::{ElementResult, ElementType};
use crate::error::{RenderingError, ValueErrorKind};
use crate::filter::Filter;
use crate::length::*;
-use crate::node::{CascadedValues, ElementType, NodeBorrow, NodeResult, NodeTrait, RsvgNode};
+use crate::node::{CascadedValues, NodeBorrow, NodeTrait, RsvgNode};
use crate::parsers::ParseValue;
use crate::properties::ComputedValues;
use crate::property_bag::PropertyBag;
@@ -113,7 +114,7 @@ impl Primitive {
}
impl NodeTrait for Primitive {
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
// With ObjectBoundingBox, only fractions and percents are allowed.
let primitiveunits = parent
.and_then(|parent| {
@@ -218,7 +219,7 @@ impl PrimitiveWithInput {
}
impl NodeTrait for PrimitiveWithInput {
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
diff --git a/rsvg_internals/src/filters/morphology.rs b/rsvg_internals/src/filters/morphology.rs
index 719bbc1d..b229730c 100644
--- a/rsvg_internals/src/filters/morphology.rs
+++ b/rsvg_internals/src/filters/morphology.rs
@@ -5,8 +5,9 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::ElementResult;
use crate::error::*;
-use crate::node::{NodeResult, NodeTrait, RsvgNode};
+use crate::node::{NodeTrait, RsvgNode};
use crate::parsers::{NumberOptionalNumber, Parse, ParseValue};
use crate::property_bag::PropertyBag;
use crate::rect::IRect;
@@ -47,7 +48,7 @@ impl Default for FeMorphology {
impl NodeTrait for FeMorphology {
impl_node_as_filter_effect!();
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
diff --git a/rsvg_internals/src/filters/offset.rs b/rsvg_internals/src/filters/offset.rs
index 0604d9ae..0ff30d7c 100644
--- a/rsvg_internals/src/filters/offset.rs
+++ b/rsvg_internals/src/filters/offset.rs
@@ -2,7 +2,8 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
-use crate::node::{NodeResult, NodeTrait, RsvgNode};
+use crate::element::ElementResult;
+use crate::node::{NodeTrait, RsvgNode};
use crate::parsers::ParseValue;
use crate::property_bag::PropertyBag;
@@ -31,7 +32,7 @@ impl Default for FeOffset {
impl NodeTrait for FeOffset {
impl_node_as_filter_effect!();
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
diff --git a/rsvg_internals/src/filters/tile.rs b/rsvg_internals/src/filters/tile.rs
index c8dbfdc4..1670e28e 100644
--- a/rsvg_internals/src/filters/tile.rs
+++ b/rsvg_internals/src/filters/tile.rs
@@ -1,6 +1,7 @@
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
-use crate::node::{NodeResult, NodeTrait, RsvgNode};
+use crate::element::ElementResult;
+use crate::node::{NodeTrait, RsvgNode};
use crate::property_bag::PropertyBag;
use super::context::{FilterContext, FilterInput, FilterOutput, FilterResult};
@@ -24,7 +25,7 @@ impl Default for FeTile {
impl NodeTrait for FeTile {
impl_node_as_filter_effect!();
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)
}
}
diff --git a/rsvg_internals/src/filters/turbulence.rs b/rsvg_internals/src/filters/turbulence.rs
index d7fa55eb..2d359ebe 100644
--- a/rsvg_internals/src/filters/turbulence.rs
+++ b/rsvg_internals/src/filters/turbulence.rs
@@ -3,8 +3,9 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::ElementResult;
use crate::error::*;
-use crate::node::{CascadedValues, NodeResult, NodeTrait, RsvgNode};
+use crate::node::{CascadedValues, NodeTrait, RsvgNode};
use crate::parsers::{NumberOptionalNumber, Parse, ParseValue};
use crate::property_bag::PropertyBag;
use crate::surface_utils::{
@@ -59,7 +60,7 @@ impl NodeTrait for FeTurbulence {
impl_node_as_filter_effect!();
#[inline]
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.base.set_atts(parent, pbag)?;
for (attr, value) in pbag.iter() {
diff --git a/rsvg_internals/src/gradient.rs b/rsvg_internals/src/gradient.rs
index ff08efdf..2d085948 100644
--- a/rsvg_internals/src/gradient.rs
+++ b/rsvg_internals/src/gradient.rs
@@ -9,9 +9,10 @@ use crate::bbox::*;
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNode, AcquiredNodes, NodeStack};
use crate::drawing_ctx::{DrawingCtx, ViewParams};
+use crate::element::{ElementResult, ElementType};
use crate::error::*;
use crate::length::*;
-use crate::node::{CascadedValues, ElementType, NodeBorrow, NodeResult, NodeTrait, RsvgNode};
+use crate::node::{CascadedValues, NodeBorrow, NodeTrait, RsvgNode};
use crate::paint_server::{AsPaintSource, PaintSource};
use crate::parsers::{Parse, ParseValue};
use crate::properties::ComputedValues;
@@ -129,7 +130,7 @@ fn validate_offset(length: Length<Both>) -> Result<Length<Both>, ValueErrorKind>
}
impl NodeTrait for Stop {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "offset") => {
@@ -575,7 +576,7 @@ impl_get_unresolved!(LinearGradient);
impl_get_unresolved!(RadialGradient);
impl Common {
- fn set_atts(&mut self, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "gradientUnits") => self.units = Some(attr.parse(value)?),
@@ -595,7 +596,7 @@ impl Common {
}
impl NodeTrait for LinearGradient {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.common.set_atts(pbag)?;
for (attr, value) in pbag.iter() {
@@ -614,7 +615,7 @@ impl NodeTrait for LinearGradient {
}
impl NodeTrait for RadialGradient {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
self.common.set_atts(pbag)?;
for (attr, value) in pbag.iter() {
@@ -813,8 +814,9 @@ fn acquire_gradient(
mod tests {
use super::*;
use crate::float_eq_cairo::ApproxEqCairo;
- use crate::node::{ElementType, NodeData, RsvgNode};
+ use crate::node::{NodeData, RsvgNode};
use markup5ever::{namespace_url, ns, QualName};
+ use std::ptr;
#[test]
fn parses_spread_method() {
@@ -846,12 +848,11 @@ mod tests {
#[test]
fn gradient_resolved_from_defaults_is_really_resolved() {
+ let bag = unsafe { PropertyBag::new_from_xml2_attributes(0, ptr::null()) };
+
let node = RsvgNode::new(NodeData::new_element(
- ElementType::LinearGradient,
&QualName::new(None, ns!(svg), local_name!("linearGradient")),
- None,
- None,
- Box::new(LinearGradient::default()),
+ &bag,
));
let borrow = node.borrow_element();
@@ -861,11 +862,8 @@ mod tests {
assert!(gradient.is_resolved());
let node = RsvgNode::new(NodeData::new_element(
- ElementType::RadialGradient,
&QualName::new(None, ns!(svg), local_name!("radialGradient")),
- None,
- None,
- Box::new(RadialGradient::default()),
+ &bag,
));
let borrow = node.borrow_element();
diff --git a/rsvg_internals/src/image.rs b/rsvg_internals/src/image.rs
index 340b6bda..14c5fa5b 100644
--- a/rsvg_internals/src/image.rs
+++ b/rsvg_internals/src/image.rs
@@ -7,6 +7,7 @@ use crate::aspect_ratio::AspectRatio;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::{ClipMode, DrawingCtx, ViewParams};
+use crate::element::ElementResult;
use crate::error::*;
use crate::length::*;
use crate::node::*;
@@ -27,7 +28,7 @@ pub struct Image {
}
impl NodeTrait for Image {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "x") => self.x = attr.parse(value)?,
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 7f589e5c..0939d062 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -86,12 +86,12 @@ mod aspect_ratio;
mod bbox;
mod color;
mod cond;
-mod create_node;
mod css;
mod dasharray;
mod document;
mod dpi;
mod drawing_ctx;
+mod element;
mod error;
mod filter;
pub mod filters;
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index 55065077..6f4ca74a 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -12,6 +12,7 @@ use crate::aspect_ratio::*;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::{ElementResult, ElementType};
use crate::error::*;
use crate::float_eq_cairo::ApproxEqCairo;
use crate::iri::IRI;
@@ -175,7 +176,7 @@ impl Marker {
}
impl NodeTrait for Marker {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "markerUnits") => self.units = attr.parse(value)?,
diff --git a/rsvg_internals/src/node.rs b/rsvg_internals/src/node.rs
index 009dbb82..668d7d89 100644
--- a/rsvg_internals/src/node.rs
+++ b/rsvg_internals/src/node.rs
@@ -5,33 +5,26 @@
//! Librsvg puts a [`NodeData`] as the type parameter of [`Node`]. For convenience,
//! librsvg has a type alias `RsvgNode = Node<NodeData>`.
//!
-//! Nodes are not constructed directly by callers; this is done in the [`create_node`] module.
+//! Nodes are not constructed directly by callers;
//!
//! [rctree]: ../../rctree/index.html
//! [`Node`]: ../../rctree/struct.Node.html
//! [`NodeData`]: struct.NodeData.html
-//! [`create_node`]: ../create_node/index.html
use downcast_rs::*;
-use locale_config::Locale;
-use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
+use markup5ever::QualName;
use std::cell::{Ref, RefMut};
-use std::collections::HashSet;
use std::fmt;
use crate::bbox::BoundingBox;
-use crate::cond::{RequiredExtensions, RequiredFeatures, SystemLanguage};
-use crate::css::Declaration;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::*;
use crate::error::*;
use crate::filters::FilterEffect;
-use crate::parsers::Parse;
-use crate::properties::{ComputedValues, SpecifiedValue, SpecifiedValues};
+use crate::properties::{ComputedValues, SpecifiedValues};
use crate::property_bag::PropertyBag;
-use crate::property_defs::Overflow;
use crate::text::NodeChars;
-use crate::transform::Transform;
/// Strong reference to an element in the SVG tree.
///
@@ -82,44 +75,9 @@ pub enum NodeData {
Text(NodeChars),
}
-/// Contents of an element node in the DOM
-pub struct Element {
- element_type: ElementType,
- element_name: QualName,
- id: Option<String>, // id attribute from XML element
- class: Option<String>, // class attribute from XML element
- specified_values: SpecifiedValues,
- important_styles: HashSet<QualName>,
- result: NodeResult,
- transform: Transform,
- values: ComputedValues,
- cond: bool,
- style_attr: String,
- node_impl: Box<dyn NodeTrait>,
-}
-
impl NodeData {
- pub fn new_element(
- element_type: ElementType,
- element_name: &QualName,
- id: Option<&str>,
- class: Option<&str>,
- node_impl: Box<dyn NodeTrait>,
- ) -> NodeData {
- NodeData::Element(Box::new(Element {
- element_type,
- element_name: element_name.clone(),
- id: id.map(str::to_string),
- class: class.map(str::to_string),
- specified_values: Default::default(),
- important_styles: Default::default(),
- transform: Default::default(),
- result: Ok(()),
- values: ComputedValues::default(),
- cond: true,
- style_attr: String::new(),
- node_impl,
- }))
+ pub fn new_element(name: &QualName, pbag: &PropertyBag) -> NodeData {
+ NodeData::Element(Box::new(create_element(name, pbag)))
}
pub fn new_chars() -> NodeData {
@@ -127,184 +85,6 @@ impl NodeData {
}
}
-impl Element {
- pub fn get_type(&self) -> ElementType {
- self.element_type
- }
-
- pub fn get_node_trait(&self) -> &dyn NodeTrait {
- self.node_impl.as_ref()
- }
-
- pub fn get_impl<T: NodeTrait>(&self) -> &T {
- if let Some(t) = (&self.node_impl).downcast_ref::<T>() {
- t
- } else {
- panic!("could not downcast");
- }
- }
-
- pub fn element_name(&self) -> &QualName {
- &self.element_name
- }
-
- pub fn get_id(&self) -> Option<&str> {
- self.id.as_ref().map(String::as_str)
- }
-
- pub fn get_class(&self) -> Option<&str> {
- self.class.as_ref().map(String::as_str)
- }
-
- pub fn get_cond(&self) -> bool {
- self.cond
- }
-
- pub fn get_transform(&self) -> Transform {
- self.transform
- }
-
- pub fn is_overflow(&self) -> bool {
- self.specified_values.is_overflow()
- }
-
- pub fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>, locale: &Locale) {
- if self.node_impl.overflow_hidden() {
- self.specified_values.overflow = SpecifiedValue::Specified(Overflow::Hidden);
- }
-
- self.save_style_attribute(pbag);
-
- if let Err(e) = self
- .set_transform_attribute(pbag)
- .and_then(|_| self.set_conditional_processing_attributes(pbag, locale))
- .and_then(|_| self.node_impl.set_atts(parent, pbag))
- .and_then(|_| self.set_presentation_attributes(pbag))
- {
- self.set_error(e);
- }
-
- self.node_impl
- .set_overridden_properties(&mut self.specified_values);
- }
-
- fn save_style_attribute(&mut self, pbag: &PropertyBag<'_>) {
- for (attr, value) in pbag.iter() {
- match attr.expanded() {
- expanded_name!("", "style") => self.style_attr.push_str(value),
- _ => (),
- }
- }
- }
-
- fn set_transform_attribute(&mut self, pbag: &PropertyBag<'_>) -> Result<(), NodeError> {
- for (attr, value) in pbag.iter() {
- match attr.expanded() {
- expanded_name!("", "transform") => {
- return Transform::parse_str(value)
- .attribute(attr)
- .and_then(|affine| {
- self.transform = affine;
- Ok(())
- });
- }
- _ => (),
- }
- }
-
- Ok(())
- }
-
- fn set_conditional_processing_attributes(
- &mut self,
- pbag: &PropertyBag<'_>,
- locale: &Locale,
- ) -> Result<(), NodeError> {
- let mut cond = self.cond;
-
- for (attr, value) in pbag.iter() {
- let mut parse = || -> Result<_, ValueErrorKind> {
- match attr.expanded() {
- expanded_name!("", "requiredExtensions") if cond => {
- cond = RequiredExtensions::from_attribute(value)
- .map(|RequiredExtensions(res)| res)?;
- }
-
- expanded_name!("", "requiredFeatures") if cond => {
- cond = RequiredFeatures::from_attribute(value)
- .map(|RequiredFeatures(res)| res)?;
- }
-
- expanded_name!("", "systemLanguage") if cond => {
- cond = SystemLanguage::from_attribute(value, locale)
- .map(|SystemLanguage(res)| res)?;
- }
-
- _ => {}
- }
-
- Ok(cond)
- };
-
- parse().map(|c| self.cond = c).attribute(attr)?;
- }
-
- Ok(())
- }
-
- /// Hands the pbag to the node's state, to apply the presentation attributes
- fn set_presentation_attributes(&mut self, pbag: &PropertyBag<'_>) -> Result<(), NodeError> {
- match self.specified_values.parse_presentation_attributes(pbag) {
- Ok(_) => Ok(()),
- Err(e) => {
- // FIXME: we'll ignore errors here for now.
- //
- // If we set the node to be in error, we expose buggy handling of the
- // enable-background property; we are not parsing it correctly. This
- // causes tests/fixtures/reftests/bugs/587721-text-transform.svg to fail
- // because it has enable-background="new 0 0 1179.75118 687.74173" in the
- // toplevel svg element.
- //
- // self.set_error(e);
- // return;
-
- rsvg_log!("(attribute error: {})", e);
- Ok(())
- }
- }
- }
-
- // Applies a style declaration to the node's specified_values
- pub fn apply_style_declaration(&mut self, declaration: &Declaration) {
- self.specified_values
- .set_property_from_declaration(declaration, &mut self.important_styles);
- }
-
- /// Applies CSS styles from the saved value of the "style" attribute
- pub fn set_style_attribute(&mut self) {
- if !self.style_attr.is_empty() {
- if let Err(e) = self
- .specified_values
- .parse_style_declarations(self.style_attr.as_str(), &mut self.important_styles)
- {
- self.set_error(e);
- }
-
- self.style_attr.clear();
- self.style_attr.shrink_to_fit();
- }
- }
-
- fn set_error(&mut self, error: NodeError) {
- rsvg_log!("setting node {} in error: {}", self, error);
- self.result = Err(error);
- }
-
- pub fn is_in_error(&self) -> bool {
- self.result.is_err()
- }
-}
-
impl fmt::Display for NodeData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
@@ -320,14 +100,6 @@ impl fmt::Display for NodeData {
}
}
-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(())
- }
-}
-
/// Can obtain computed values from a node
///
/// In our tree of SVG elements (Node in our parlance), each node stores a `ComputedValues` that
@@ -382,7 +154,7 @@ impl<'a> CascadedValues<'a> {
pub fn new_from_values(node: &'a RsvgNode, values: &ComputedValues) -> CascadedValues<'a> {
let mut v = values.clone();
node.borrow_element()
- .specified_values
+ .get_specified_values()
.to_computed_values(&mut v);
CascadedValues {
@@ -396,7 +168,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 element) => &element.values,
+ CascadedInner::FromNode(ref e) => e.get_computed_values(),
CascadedInner::FromValues(ref v) => v,
}
}
@@ -407,7 +179,7 @@ pub trait NodeTrait: Downcast {
/// Sets per-node attributes from the `pbag`
///
/// Each node is supposed to iterate the `pbag`, and parse any attributes it needs.
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult;
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult;
/// Sets any special-cased properties that the node may have, that are different
/// from defaults in the node's `SpecifiedValues`.
@@ -439,85 +211,6 @@ pub trait NodeTrait: Downcast {
impl_downcast!(NodeTrait);
-// After creating/parsing a Node, it will be in a success or an error state.
-// We represent this with a Result, aliased as a NodeResult. There is no
-// extra information for the Ok case; all the interesting stuff is in the
-// Err case.
-//
-// https://www.w3.org/TR/SVG/implnote.html#ErrorProcessing
-//
-// When an element has an error during parsing, the SVG spec calls the element
-// to be "in error". We skip rendering of elements that are in error.
-//
-// When we parse an element's attributes, we stop as soon as we
-// encounter the first error: a parse error, or an invalid value,
-// etc. No further attributes will be processed, although note that
-// the order in which an element's attributes are processed is not
-// defined.
-//
-// Alternatively, we could try to parse/validate all the attributes
-// that come in an element and build up a Vec<NodeError>. However, we
-// don't do this now. Doing that may be more useful for an SVG
-// validator, not a renderer like librsvg is.
-pub type NodeResult = Result<(), NodeError>;
-
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
-pub enum ElementType {
- Circle,
- ClipPath,
- Ellipse,
- Filter,
- Group,
- Image,
- Line,
- LinearGradient,
- Link,
- Marker,
- Mask,
- NonRendering,
- Path,
- Pattern,
- Polygon,
- Polyline,
- RadialGradient,
- Rect,
- Stop,
- Style,
- Svg,
- Switch,
- Symbol,
- Text,
- TRef,
- TSpan,
- Use,
-
- // Filter primitives, these start with "Fe" as element names are e.g. "feBlend"
- FeBlend,
- FeColorMatrix,
- FeComponentTransfer,
- FeComposite,
- FeConvolveMatrix,
- FeDiffuseLighting,
- FeDisplacementMap,
- FeDistantLight,
- FeFlood,
- FeFuncA,
- FeFuncB,
- FeFuncG,
- FeFuncR,
- FeGaussianBlur,
- FeImage,
- FeMerge,
- FeMergeNode,
- FeMorphology,
- FeOffset,
- FePointLight,
- FeSpecularLighting,
- FeSpotLight,
- FeTile,
- FeTurbulence,
-}
-
/// Helper trait to get different NodeData variants
pub trait NodeBorrow {
/// Returns `false` for NodeData::Text, `true` otherwise.
@@ -591,8 +284,8 @@ impl NodeCascade for RsvgNode {
{
let mut elt = self.borrow_element_mut();
- elt.specified_values.to_computed_values(&mut values);
- elt.values = values.clone();
+ elt.get_specified_values().to_computed_values(&mut values);
+ elt.set_computed_values(&values);
}
for mut child in self.children().filter(|c| c.is_element()) {
diff --git a/rsvg_internals/src/pattern.rs b/rsvg_internals/src/pattern.rs
index 24ff7992..7525ebff 100644
--- a/rsvg_internals/src/pattern.rs
+++ b/rsvg_internals/src/pattern.rs
@@ -10,6 +10,7 @@ use crate::bbox::*;
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNodes, NodeStack};
use crate::drawing_ctx::{DrawingCtx, ViewParams};
+use crate::element::{ElementResult, ElementType};
use crate::error::*;
use crate::float_eq_cairo::ApproxEqCairo;
use crate::length::*;
@@ -118,7 +119,7 @@ pub struct Pattern {
}
impl NodeTrait for Pattern {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "patternUnits") => self.common.units = Some(attr.parse(value)?),
@@ -562,17 +563,17 @@ impl Pattern {
#[cfg(test)]
mod tests {
use super::*;
- use crate::node::{ElementType, NodeData, RsvgNode};
+ use crate::node::{NodeData, RsvgNode};
use markup5ever::{namespace_url, ns, QualName};
+ use std::ptr;
#[test]
fn pattern_resolved_from_defaults_is_really_resolved() {
+ let bag = unsafe { PropertyBag::new_from_xml2_attributes(0, ptr::null()) };
+
let node = RsvgNode::new(NodeData::new_element(
- ElementType::Pattern,
&QualName::new(None, ns!(svg), local_name!("pattern")),
- None,
- None,
- Box::new(Pattern::default()),
+ &bag,
));
let borrow = node.borrow_element();
diff --git a/rsvg_internals/src/shapes.rs b/rsvg_internals/src/shapes.rs
index ea0c5888..d1fb0330 100644
--- a/rsvg_internals/src/shapes.rs
+++ b/rsvg_internals/src/shapes.rs
@@ -8,6 +8,7 @@ use std::rc::Rc;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::ElementResult;
use crate::error::*;
use crate::length::*;
use crate::node::*;
@@ -115,7 +116,7 @@ pub struct Path {
}
impl NodeTrait for Path {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
if attr.expanded() == expanded_name!("", "d") {
let mut builder = PathBuilder::new();
@@ -219,7 +220,7 @@ pub struct Polygon {
}
impl NodeTrait for Polygon {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
if attr.expanded() == expanded_name!("", "points") {
self.points = attr.parse(value).map(Some)?;
@@ -254,7 +255,7 @@ pub struct Polyline {
}
impl NodeTrait for Polyline {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
if attr.expanded() == expanded_name!("", "points") {
self.points = attr.parse(value).map(Some)?;
@@ -290,7 +291,7 @@ pub struct Line {
}
impl NodeTrait for Line {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "x1") => self.x1 = attr.parse(value)?,
@@ -352,7 +353,7 @@ pub struct Rect {
}
impl NodeTrait for Rect {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "x") => self.x = attr.parse(value)?,
@@ -580,7 +581,7 @@ pub struct Circle {
}
impl NodeTrait for Circle {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "cx") => self.cx = attr.parse(value)?,
@@ -633,7 +634,7 @@ pub struct Ellipse {
}
impl NodeTrait for Ellipse {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "cx") => self.cx = attr.parse(value)?,
diff --git a/rsvg_internals/src/structure.rs b/rsvg_internals/src/structure.rs
index e87992c5..06ae97d0 100644
--- a/rsvg_internals/src/structure.rs
+++ b/rsvg_internals/src/structure.rs
@@ -9,6 +9,7 @@ use crate::coord_units::CoordUnits;
use crate::document::AcquiredNodes;
use crate::dpi::Dpi;
use crate::drawing_ctx::{ClipMode, DrawingCtx, ViewParams};
+use crate::element::ElementResult;
use crate::error::*;
use crate::length::*;
use crate::node::*;
@@ -22,7 +23,7 @@ use crate::viewbox::*;
pub struct Group();
impl NodeTrait for Group {
- fn set_atts(&mut self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> ElementResult {
Ok(())
}
@@ -50,7 +51,7 @@ impl NodeTrait for Group {
pub struct NonRendering;
impl NodeTrait for NonRendering {
- fn set_atts(&mut self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> ElementResult {
Ok(())
}
}
@@ -59,7 +60,7 @@ impl NodeTrait for NonRendering {
pub struct Switch();
impl NodeTrait for Switch {
- fn set_atts(&mut self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, _: &PropertyBag<'_>) -> ElementResult {
Ok(())
}
@@ -183,7 +184,7 @@ impl Svg {
}
impl NodeTrait for Svg {
- fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
// x & y attributes have no effect on outermost svg
// http://www.w3.org/TR/SVG/struct.html#SVGElement
let is_inner_svg = parent.is_some();
@@ -308,7 +309,7 @@ impl Use {
}
impl NodeTrait for Use {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!(xlink "href") => {
@@ -362,7 +363,7 @@ impl Symbol {
}
impl NodeTrait for Symbol {
- fn set_atts(&mut self, _parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "preserveAspectRatio") => {
@@ -395,7 +396,7 @@ impl ClipPath {
}
impl NodeTrait for ClipPath {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "clipPathUnits") => self.units = attr.parse(value)?,
@@ -455,7 +456,7 @@ impl Mask {
}
impl NodeTrait for Mask {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "x") => self.x = attr.parse(value)?,
@@ -484,7 +485,7 @@ pub struct Link {
}
impl NodeTrait for Link {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!(xlink "href") => self.link = Some(value.to_owned()),
diff --git a/rsvg_internals/src/style.rs b/rsvg_internals/src/style.rs
index 2d73afba..9f7d3172 100644
--- a/rsvg_internals/src/style.rs
+++ b/rsvg_internals/src/style.rs
@@ -2,8 +2,9 @@
use markup5ever::{expanded_name, local_name, namespace_url, ns};
+use crate::element::ElementResult;
use crate::error::*;
-use crate::node::{NodeResult, NodeTrait, RsvgNode};
+use crate::node::{NodeTrait, RsvgNode};
use crate::property_bag::PropertyBag;
/// Represents the syntax used in the <style> node.
@@ -51,7 +52,7 @@ impl Style {
}
impl NodeTrait for Style {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
if attr.expanded() == expanded_name!("", "type") {
self.type_ = Some(StyleType::parse(value).attribute(attr)?);
diff --git a/rsvg_internals/src/text.rs b/rsvg_internals/src/text.rs
index 3db1bc34..da8c2b99 100644
--- a/rsvg_internals/src/text.rs
+++ b/rsvg_internals/src/text.rs
@@ -8,11 +8,12 @@ use crate::allowed_url::Fragment;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
+use crate::element::{ElementResult, ElementType};
use crate::error::*;
use crate::float_eq_cairo::ApproxEqCairo;
use crate::font_props::FontWeightSpec;
use crate::length::*;
-use crate::node::{CascadedValues, ElementType, NodeBorrow, NodeResult, NodeTrait, RsvgNode};
+use crate::node::{CascadedValues, NodeBorrow, NodeTrait, RsvgNode};
use crate::parsers::ParseValue;
use crate::properties::ComputedValues;
use crate::property_bag::PropertyBag;
@@ -604,7 +605,7 @@ impl Text {
}
impl NodeTrait for Text {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "x") => self.x = attr.parse(value)?,
@@ -723,7 +724,7 @@ fn extract_chars_children_to_chunks_recursively(
}
impl NodeTrait for TRef {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!(xlink "href") => {
@@ -775,7 +776,7 @@ impl TSpan {
}
impl NodeTrait for TSpan {
- fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+ fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> ElementResult {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!("", "x") => self.x = attr.parse(value).map(Some)?,
diff --git a/rsvg_internals/src/xml.rs b/rsvg_internals/src/xml.rs
index 91c1a7fa..077a8748 100644
--- a/rsvg_internals/src/xml.rs
+++ b/rsvg_internals/src/xml.rs
@@ -13,10 +13,11 @@ use std::str;
use crate::allowed_url::AllowedUrl;
use crate::document::{Document, DocumentBuilder};
+use crate::element::ElementType;
use crate::error::LoadingError;
use crate::io::{self, get_input_stream_for_loading};
use crate::limits::MAX_LOADED_ELEMENTS;
-use crate::node::{ElementType, NodeBorrow, RsvgNode};
+use crate::node::{NodeBorrow, RsvgNode};
use crate::property_bag::PropertyBag;
use crate::style::{Style, StyleType};
use crate::xml2_load::Xml2Parser;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]