[librsvg: 1/7] element: set the correct SpecifiedValues at creation



commit 910d6d20ba46e70662b99db35405630c4f9775d8
Author: Paolo Borelli <pborelli gnome org>
Date:   Tue Mar 17 17:30:14 2020 +0100

    element: set the correct SpecifiedValues at creation
    
    Instead of overriding in set_atts, use our creation table to
    capture the fact that different elements have different defaults.

 rsvg_internals/src/element.rs    | 237 +++++++++++++++++++++------------------
 rsvg_internals/src/image.rs      |   4 -
 rsvg_internals/src/marker.rs     |   4 -
 rsvg_internals/src/pattern.rs    |   4 -
 rsvg_internals/src/properties.rs |   9 ++
 rsvg_internals/src/structure.rs  |   8 --
 6 files changed, 138 insertions(+), 128 deletions(-)
---
diff --git a/rsvg_internals/src/element.rs b/rsvg_internals/src/element.rs
index 44d7098c..68d17a9d 100644
--- a/rsvg_internals/src/element.rs
+++ b/rsvg_internals/src/element.rs
@@ -46,9 +46,8 @@ use crate::marker::Marker;
 use crate::node::*;
 use crate::parsers::Parse;
 use crate::pattern::Pattern;
-use crate::properties::{ComputedValues, SpecifiedValue, SpecifiedValues};
+use crate::properties::{ComputedValues, 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;
@@ -145,12 +144,6 @@ pub trait ElementTrait: Downcast {
     /// from defaults in the element's `SpecifiedValues`.
     fn set_overridden_properties(&self, _values: &mut SpecifiedValues) {}
 
-    /// Whether this element has overflow:hidden.
-    /// https://www.w3.org/TR/SVG/styling.html#UAStyleSheet
-    fn overflow_hidden(&self) -> bool {
-        false
-    }
-
     fn draw(
         &self,
         _node: &Node,
@@ -241,10 +234,6 @@ impl Element {
     }
 
     pub fn set_atts(&mut self, parent: Option<&Node>, pbag: &PropertyBag<'_>, locale: &Locale) {
-        if self.element_impl.overflow_hidden() {
-            self.specified_values.overflow = SpecifiedValue::Specified(Overflow::Hidden);
-        }
-
         self.save_style_attribute(pbag);
 
         if let Err(e) = self
@@ -387,13 +376,18 @@ impl fmt::Display for Element {
 
 macro_rules! e {
     ($name:ident, $element_type:ident) => {
-        pub fn $name(element_name: &QualName, id: Option<&str>, class: Option<&str>) -> Element {
+        pub fn $name(
+            element_name: &QualName,
+            id: Option<&str>,
+            class: Option<&str>,
+            specified_values: SpecifiedValues,
+        ) -> 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(),
+                specified_values,
                 important_styles: Default::default(),
                 transform: Default::default(),
                 result: Ok(()),
@@ -479,100 +473,115 @@ mod creators {
 
 use creators::*;
 
-type ElementCreateFn =
-    fn(element_name: &QualName, id: Option<&str>, class: Option<&str>) -> Element;
+type ElementCreateFn = fn(
+    element_name: &QualName,
+    id: Option<&str>,
+    class: Option<&str>,
+    specified_values: SpecifiedValues,
+) -> Element;
+
+// For now it's just an enum, if some element needs more than one flag
+// we will need something fancier
+#[derive(Copy, Clone, PartialEq)]
+enum ElementCreateFlags {
+    Default,
+    IgnoreClass,
+    OverflowHidden,
+}
 
 // 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![
+static ELEMENT_CREATORS: Lazy<HashMap<&'static str, (ElementCreateFn, ElementCreateFlags)>> = Lazy::new(|| {
+    use ElementCreateFlags::*;
+
+    let creators_table: Vec<(&str, ElementCreateFn, ElementCreateFlags)> = 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, ), */
+        ("a",                   create_link,                  Default),
+        /* ("altGlyph",         ), */
+        /* ("altGlyphDef",      ), */
+        /* ("altGlyphItem",     ), */
+        /* ("animate",          ), */
+        /* ("animateColor",     ), */
+        /* ("animateMotion",    ), */
+        /* ("animateTransform", ), */
+        ("circle",              create_circle,                Default),
+        ("clipPath",            create_clip_path,             Default),
+        /* ("color-profile",    ), */
+        /* ("cursor",           ), */
+        ("defs",                create_defs,                  Default),
+        /* ("desc",             ), */
+        ("ellipse",             create_ellipse,               Default),
+        ("feBlend",             create_fe_blend,              Default),
+        ("feColorMatrix",       create_fe_color_matrix,       Default),
+        ("feComponentTransfer", create_fe_component_transfer, Default),
+        ("feComposite",         create_fe_composite,          Default),
+        ("feConvolveMatrix",    create_fe_convolve_matrix,    Default),
+        ("feDiffuseLighting",   create_fe_diffuse_lighting,   Default),
+        ("feDisplacementMap",   create_fe_displacement_map,   Default),
+        ("feDistantLight",      create_fe_distant_light,      IgnoreClass),
+        ("feFuncA",             create_fe_func_a,             IgnoreClass),
+        ("feFuncB",             create_fe_func_b,             IgnoreClass),
+        ("feFuncG",             create_fe_func_g,             IgnoreClass),
+        ("feFuncR",             create_fe_func_r,             IgnoreClass),
+        ("feFlood",             create_fe_flood,              Default),
+        ("feGaussianBlur",      create_fe_gaussian_blur,      Default),
+        ("feImage",             create_fe_image,              Default),
+        ("feMerge",             create_fe_merge,              Default),
+        ("feMergeNode",         create_fe_merge_node,         IgnoreClass),
+        ("feMorphology",        create_fe_morphology,         Default),
+        ("feOffset",            create_fe_offset,             Default),
+        ("fePointLight",        create_fe_point_light,        IgnoreClass),
+        ("feSpecularLighting",  create_fe_specular_lighting,  Default),
+        ("feSpotLight",         create_fe_spot_light,         IgnoreClass),
+        ("feTile",              create_fe_tile,               Default),
+        ("feTurbulence",        create_fe_turbulence,         Default),
+        ("filter",              create_filter,                Default),
+        /* ("font",             ), */
+        /* ("font-face",        ), */
+        /* ("font-face-format", ), */
+        /* ("font-face-name",   ), */
+        /* ("font-face-src",    ), */
+        /* ("font-face-uri",    ), */
+        /* ("foreignObject",    ), */
+        ("g",                   create_group,                 Default),
+        /* ("glyph",            ), */
+        /* ("glyphRef",         ), */
+        /* ("hkern",            ), */
+        ("image",               create_image,                 OverflowHidden),
+        ("line",                create_line,                  Default),
+        ("linearGradient",      create_linear_gradient,       Default),
+        ("marker",              create_marker,                OverflowHidden),
+        ("mask",                create_mask,                  Default),
+        /* ("metadata",         ), */
+        /* ("missing-glyph",    ), */
+        /* ("mpath",            ), */
+        /* ("multiImage",       ), */
+        ("path",                create_path,                  Default),
+        ("pattern",             create_pattern,               OverflowHidden),
+        ("polygon",             create_polygon,               Default),
+        ("polyline",            create_polyline,              Default),
+        ("radialGradient",      create_radial_gradient,       Default),
+        ("rect",                create_rect,                  Default),
+        /* ("script",           ), */
+        /* ("set",              ), */
+        ("stop",                create_stop,                  Default),
+        ("style",               create_style,                 IgnoreClass),
+        /* ("subImage",         ), */
+        /* ("subImageRef",      ), */
+        ("svg",                 create_svg,                   OverflowHidden),
+        ("switch",              create_switch,                Default),
+        ("symbol",              create_symbol,                OverflowHidden),
+        ("text",                create_text,                  Default),
+        /* ("textPath",         ), */
+        /* ("title",            ), */
+        ("tref",                create_tref,                  Default),
+        ("tspan",               create_tspan,                 Default),
+        ("use",                 create_use,                   Default),
+        /* ("view",             ), */
+        /* ("vkern",            ), */
     ];
 
-    creators_table.into_iter().map(|(n, s, f)| (n, (s, f))).collect()
+    creators_table.into_iter().map(|(n, c, f)| (n, (c, f))).collect()
 });
 
 /// Takes an XML element name and a list of attribute/value pairs and creates an [`Element`].
@@ -594,27 +603,39 @@ pub fn create_element(name: &QualName, pbag: &PropertyBag) -> Element {
         }
     }
 
-    let (supports_class, create_fn) = if name.ns == ns!(svg) {
+    let (create_fn, flags) = 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),
+            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 => (true, create_non_rendering as ElementCreateFn),
+            None => (
+                create_non_rendering as ElementCreateFn,
+                ElementCreateFlags::Default,
+            ),
         }
     } else {
-        (true, create_non_rendering as ElementCreateFn)
+        (
+            create_non_rendering as ElementCreateFn,
+            ElementCreateFlags::Default,
+        )
     };
 
-    if !supports_class {
+    if flags == ElementCreateFlags::IgnoreClass {
         class = None;
     };
 
+    let specified_values = if flags == ElementCreateFlags::OverflowHidden {
+        SpecifiedValues::with_overflow_hidden()
+    } else {
+        SpecifiedValues::default()
+    };
+
     //    sizes::print_sizes();
 
-    create_fn(name, id, class)
+    create_fn(name, id, class, specified_values)
 }
 
 #[cfg(ignore)]
diff --git a/rsvg_internals/src/image.rs b/rsvg_internals/src/image.rs
index 247355ac..55c884cc 100644
--- a/rsvg_internals/src/image.rs
+++ b/rsvg_internals/src/image.rs
@@ -57,10 +57,6 @@ impl ElementTrait for Image {
         Ok(())
     }
 
-    fn overflow_hidden(&self) -> bool {
-        true
-    }
-
     fn draw(
         &self,
         node: &Node,
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index 3c49725a..70593e2d 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -200,10 +200,6 @@ impl ElementTrait for Marker {
         Ok(())
     }
 
-    fn overflow_hidden(&self) -> bool {
-        true
-    }
-
     fn set_overridden_properties(&self, values: &mut SpecifiedValues) {
         // markers are always displayed, even if <marker> or its ancestors are display:none
         values.display = SpecifiedValue::Specified(Default::default());
diff --git a/rsvg_internals/src/pattern.rs b/rsvg_internals/src/pattern.rs
index 0cbedb87..870c953b 100644
--- a/rsvg_internals/src/pattern.rs
+++ b/rsvg_internals/src/pattern.rs
@@ -153,10 +153,6 @@ impl ElementTrait for Pattern {
 
         Ok(())
     }
-
-    fn overflow_hidden(&self) -> bool {
-        true
-    }
 }
 
 impl PaintSource for Pattern {
diff --git a/rsvg_internals/src/properties.rs b/rsvg_internals/src/properties.rs
index e13f8c10..3ea83485 100644
--- a/rsvg_internals/src/properties.rs
+++ b/rsvg_internals/src/properties.rs
@@ -175,6 +175,15 @@ pub struct SpecifiedValues {
     pub xml_space: SpecifiedValue<XmlSpace>, // not a property, but a non-presentation attribute
 }
 
+impl SpecifiedValues {
+    pub fn with_overflow_hidden() -> SpecifiedValues {
+        SpecifiedValues {
+            overflow: SpecifiedValue::Specified(Overflow::Hidden),
+            ..Default::default()
+        }
+    }
+}
+
 #[derive(Debug, Default, Clone)]
 pub struct ComputedValues {
     pub baseline_shift: BaselineShift,
diff --git a/rsvg_internals/src/structure.rs b/rsvg_internals/src/structure.rs
index c25784ad..03fa30d5 100644
--- a/rsvg_internals/src/structure.rs
+++ b/rsvg_internals/src/structure.rs
@@ -213,10 +213,6 @@ impl ElementTrait for Svg {
         Ok(())
     }
 
-    fn overflow_hidden(&self) -> bool {
-        true
-    }
-
     fn draw(
         &self,
         node: &Node,
@@ -376,10 +372,6 @@ impl ElementTrait for Symbol {
 
         Ok(())
     }
-
-    fn overflow_hidden(&self) -> bool {
-        true
-    }
 }
 
 coord_units!(ClipPathUnits, CoordUnits::UserSpaceOnUse);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]