1
//! SVG Elements.
2

            
3
use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
4
use std::collections::{HashMap, HashSet};
5
use std::fmt;
6
use std::sync::OnceLock;
7

            
8
use crate::accept_language::UserLanguage;
9
use crate::bbox::BoundingBox;
10
use crate::cond::{RequiredExtensions, RequiredFeatures, SystemLanguage};
11
use crate::css::{Declaration, Origin};
12
use crate::document::AcquiredNodes;
13
use crate::drawing_ctx::{DrawingCtx, Viewport};
14
use crate::error::*;
15
use crate::filter::Filter;
16
use crate::filters::{
17
    blend::FeBlend,
18
    color_matrix::FeColorMatrix,
19
    component_transfer::{FeComponentTransfer, FeFuncA, FeFuncB, FeFuncG, FeFuncR},
20
    composite::FeComposite,
21
    convolve_matrix::FeConvolveMatrix,
22
    displacement_map::FeDisplacementMap,
23
    drop_shadow::FeDropShadow,
24
    flood::FeFlood,
25
    gaussian_blur::FeGaussianBlur,
26
    image::FeImage,
27
    lighting::{FeDiffuseLighting, FeDistantLight, FePointLight, FeSpecularLighting, FeSpotLight},
28
    merge::{FeMerge, FeMergeNode},
29
    morphology::FeMorphology,
30
    offset::FeOffset,
31
    tile::FeTile,
32
    turbulence::FeTurbulence,
33
    FilterEffect,
34
};
35
use crate::gradient::{LinearGradient, RadialGradient, Stop};
36
use crate::image::Image;
37
use crate::layout::Layer;
38
use crate::marker::Marker;
39
use crate::node::*;
40
use crate::pattern::Pattern;
41
use crate::properties::{ComputedValues, SpecifiedValues};
42
use crate::rsvg_log;
43
use crate::session::Session;
44
use crate::shapes::{Circle, Ellipse, Line, Path, Polygon, Polyline, Rect};
45
use crate::structure::{ClipPath, Group, Link, Mask, NonRendering, Svg, Switch, Symbol, Use};
46
use crate::style::Style;
47
use crate::text::{TRef, TSpan, Text};
48
use crate::text2::Text2;
49
use crate::xml::Attributes;
50

            
51
pub trait ElementTrait {
52
    /// Sets per-element attributes.
53
    ///
54
    /// Each element is supposed to iterate the `attributes`, and parse any ones it needs.
55
    /// SVG specifies that unknown attributes should be ignored, and known attributes with invalid
56
    /// values should be ignored so that the attribute ends up with its "initial value".
57
    ///
58
    /// You can use the [`set_attribute`] function to do that.
59
1016921
    fn set_attributes(&mut self, _attributes: &Attributes, _session: &Session) {}
60

            
61
    /// Draw an element.
62
    ///
63
    /// Each element is supposed to draw itself as needed.
64
684
    fn draw(
65
        &self,
66
        _node: &Node,
67
        _acquired_nodes: &mut AcquiredNodes<'_>,
68
        _cascaded: &CascadedValues<'_>,
69
        _viewport: &Viewport,
70
        draw_ctx: &mut DrawingCtx,
71
        _clipping: bool,
72
    ) -> Result<BoundingBox, InternalRenderingError> {
73
        // by default elements don't draw themselves
74
684
        Ok(draw_ctx.empty_bbox())
75
684
    }
76

            
77
    /// Create a layout object for the current element.
78
    ///
79
    /// This resolves property values, coordinates, lengths, etc. and produces a layout
80
    /// item for rendering.
81
    fn layout(
82
        &self,
83
        _node: &Node,
84
        _acquired_nodes: &mut AcquiredNodes<'_>,
85
        _cascaded: &CascadedValues<'_>,
86
        _viewport: &Viewport,
87
        _draw_ctx: &mut DrawingCtx,
88
        _clipping: bool,
89
    ) -> Result<Option<Layer>, InternalRenderingError> {
90
        Ok(None)
91
    }
92
}
93

            
94
/// Sets `dest` if `parse_result` is `Ok()`, otherwise just logs the error.
95
///
96
/// Implementations of the [`ElementTrait`] trait generally scan a list of attributes
97
/// for the ones they can handle, and parse their string values.  Per the SVG spec, an attribute
98
/// with an invalid value should be ignored, and it should fall back to the default value.
99
///
100
/// In librsvg, those default values are set in each element's implementation of the [`Default`] trait:
101
/// at element creation time, each element gets initialized to its `Default`, and then each attribute
102
/// gets parsed.  This function will set that attribute's value only if parsing was successful.
103
///
104
/// In case the `parse_result` is an error, this function will log an appropriate notice
105
/// via the [`Session`].
106
9179
pub fn set_attribute<T>(dest: &mut T, parse_result: Result<T, ElementError>, session: &Session) {
107
9179
    match parse_result {
108
9171
        Ok(v) => *dest = v,
109
8
        Err(e) => {
110
            // FIXME: this does not provide a clue of what was the problematic element.
111
            // We need tracking of the current parsing position to do that.
112
            rsvg_log!(session, "ignoring attribute with invalid value: {}", e);
113
8
        }
114
    }
115
9179
}
116

            
117
pub struct Element {
118
    element_name: QualName,
119
    attributes: Attributes,
120
    specified_values: SpecifiedValues,
121
    important_styles: HashSet<QualName>,
122
    values: ComputedValues,
123
    required_extensions: Option<RequiredExtensions>,
124
    required_features: Option<RequiredFeatures>,
125
    system_language: Option<SystemLanguage>,
126
    pub element_data: ElementData,
127
}
128

            
129
impl fmt::Display for Element {
130
2006953
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131
2006953
        write!(f, "{}", self.element_name().local)?;
132
2006953
        write!(f, " id={}", self.get_id().unwrap_or("None"))?;
133
2006953
        Ok(())
134
2006953
    }
135
}
136

            
137
/// Parsed contents of an element node in the DOM.
138
///
139
/// This enum uses `Box<Foo>` in order to make each variant the size of
140
/// a pointer.
141
pub enum ElementData {
142
    Circle(Box<Circle>),
143
    ClipPath(Box<ClipPath>),
144
    Ellipse(Box<Ellipse>),
145
    Filter(Box<Filter>),
146
    Group(Box<Group>),
147
    Image(Box<Image>),
148
    Line(Box<Line>),
149
    LinearGradient(Box<LinearGradient>),
150
    Link(Box<Link>),
151
    Marker(Box<Marker>),
152
    Mask(Box<Mask>),
153
    NonRendering(Box<NonRendering>),
154
    Path(Box<Path>),
155
    Pattern(Box<Pattern>),
156
    Polygon(Box<Polygon>),
157
    Polyline(Box<Polyline>),
158
    RadialGradient(Box<RadialGradient>),
159
    Rect(Box<Rect>),
160
    Stop(Box<Stop>),
161
    Style(Box<Style>),
162
    Svg(Box<Svg>),
163
    Switch(Box<Switch>),
164
    Symbol(Box<Symbol>),
165
    Text(Box<Text>),
166
    Text2(Box<Text2>),
167
    TRef(Box<TRef>),
168
    TSpan(Box<TSpan>),
169
    Use(Box<Use>),
170

            
171
    // Filter primitives, these start with "Fe" as element names are e.g. "feBlend"
172
    FeBlend(Box<FeBlend>),
173
    FeColorMatrix(Box<FeColorMatrix>),
174
    FeComponentTransfer(Box<FeComponentTransfer>),
175
    FeComposite(Box<FeComposite>),
176
    FeConvolveMatrix(Box<FeConvolveMatrix>),
177
    FeDiffuseLighting(Box<FeDiffuseLighting>),
178
    FeDisplacementMap(Box<FeDisplacementMap>),
179
    FeDistantLight(Box<FeDistantLight>),
180
    FeDropShadow(Box<FeDropShadow>),
181
    FeFlood(Box<FeFlood>),
182
    FeFuncA(Box<FeFuncA>),
183
    FeFuncB(Box<FeFuncB>),
184
    FeFuncG(Box<FeFuncG>),
185
    FeFuncR(Box<FeFuncR>),
186
    FeGaussianBlur(Box<FeGaussianBlur>),
187
    FeImage(Box<FeImage>),
188
    FeMerge(Box<FeMerge>),
189
    FeMergeNode(Box<FeMergeNode>),
190
    FeMorphology(Box<FeMorphology>),
191
    FeOffset(Box<FeOffset>),
192
    FePointLight(Box<FePointLight>),
193
    FeSpecularLighting(Box<FeSpecularLighting>),
194
    FeSpotLight(Box<FeSpotLight>),
195
    FeTile(Box<FeTile>),
196
    FeTurbulence(Box<FeTurbulence>),
197
}
198

            
199
#[rustfmt::skip]
200
1019647
fn get_element_creators() -> &'static HashMap<&'static str, (ElementDataCreateFn, ElementCreateFlags)> {
201
    use ElementCreateFlags::*;
202

            
203
1019759
    ELEMENT_CREATORS.get_or_init(|| {
204
        // Lines in comments are elements that we don't support.
205
224
        let creators_table: Vec<(&str, ElementDataCreateFn, ElementCreateFlags)> = vec![
206
            // name, supports_class, create_fn
207
112
            ("a",                   create_link,                  Default),
208
            /* ("altGlyph",         ), */
209
            /* ("altGlyphDef",      ), */
210
            /* ("altGlyphItem",     ), */
211
            /* ("animate",          ), */
212
            /* ("animateColor",     ), */
213
            /* ("animateMotion",    ), */
214
            /* ("animateTransform", ), */
215
112
            ("circle",              create_circle,                Default),
216
112
            ("clipPath",            create_clip_path,             Default),
217
            /* ("color-profile",    ), */
218
            /* ("cursor",           ), */
219
112
            ("defs",                create_defs,                  Default),
220
            /* ("desc",             ), */
221
112
            ("ellipse",             create_ellipse,               Default),
222
112
            ("feBlend",             create_fe_blend,              Default),
223
112
            ("feColorMatrix",       create_fe_color_matrix,       Default),
224
112
            ("feComponentTransfer", create_fe_component_transfer, Default),
225
112
            ("feComposite",         create_fe_composite,          Default),
226
112
            ("feConvolveMatrix",    create_fe_convolve_matrix,    Default),
227
112
            ("feDiffuseLighting",   create_fe_diffuse_lighting,   Default),
228
112
            ("feDisplacementMap",   create_fe_displacement_map,   Default),
229
112
            ("feDistantLight",      create_fe_distant_light,      IgnoreClass),
230
112
            ("feDropShadow",        create_fe_drop_shadow,        Default),
231
112
            ("feFuncA",             create_fe_func_a,             IgnoreClass),
232
112
            ("feFuncB",             create_fe_func_b,             IgnoreClass),
233
112
            ("feFuncG",             create_fe_func_g,             IgnoreClass),
234
112
            ("feFuncR",             create_fe_func_r,             IgnoreClass),
235
112
            ("feFlood",             create_fe_flood,              Default),
236
112
            ("feGaussianBlur",      create_fe_gaussian_blur,      Default),
237
112
            ("feImage",             create_fe_image,              Default),
238
112
            ("feMerge",             create_fe_merge,              Default),
239
112
            ("feMergeNode",         create_fe_merge_node,         IgnoreClass),
240
112
            ("feMorphology",        create_fe_morphology,         Default),
241
112
            ("feOffset",            create_fe_offset,             Default),
242
112
            ("fePointLight",        create_fe_point_light,        IgnoreClass),
243
112
            ("feSpecularLighting",  create_fe_specular_lighting,  Default),
244
112
            ("feSpotLight",         create_fe_spot_light,         IgnoreClass),
245
112
            ("feTile",              create_fe_tile,               Default),
246
112
            ("feTurbulence",        create_fe_turbulence,         Default),
247
112
            ("filter",              create_filter,                Default),
248
            /* ("font",             ), */
249
            /* ("font-face",        ), */
250
            /* ("font-face-format", ), */
251
            /* ("font-face-name",   ), */
252
            /* ("font-face-src",    ), */
253
            /* ("font-face-uri",    ), */
254
            /* ("foreignObject",    ), */
255
112
            ("g",                   create_group,                 Default),
256
            /* ("glyph",            ), */
257
            /* ("glyphRef",         ), */
258
            /* ("hkern",            ), */
259
112
            ("image",               create_image,                 Default),
260
112
            ("line",                create_line,                  Default),
261
112
            ("linearGradient",      create_linear_gradient,       Default),
262
112
            ("marker",              create_marker,                Default),
263
112
            ("mask",                create_mask,                  Default),
264
            /* ("metadata",         ), */
265
            /* ("missing-glyph",    ), */
266
            /* ("mpath",            ), */
267
            /* ("multiImage",       ), */
268
112
            ("path",                create_path,                  Default),
269
112
            ("pattern",             create_pattern,               Default),
270
112
            ("polygon",             create_polygon,               Default),
271
112
            ("polyline",            create_polyline,              Default),
272
112
            ("radialGradient",      create_radial_gradient,       Default),
273
112
            ("rect",                create_rect,                  Default),
274
            /* ("script",           ), */
275
            /* ("set",              ), */
276
112
            ("stop",                create_stop,                  Default),
277
112
            ("style",               create_style,                 IgnoreClass),
278
            /* ("subImage",         ), */
279
            /* ("subImageRef",      ), */
280
112
            ("svg",                 create_svg,                   Default),
281
112
            ("switch",              create_switch,                Default),
282
112
            ("symbol",              create_symbol,                Default),
283
112
            ("text",                create_text,                  Default),
284
112
            ("text2",               create_text2,                 Default),
285
            /* ("textPath",         ), */
286
            /* ("title",            ), */
287
112
            ("tref",                create_tref,                  Default),
288
112
            ("tspan",               create_tspan,                 Default),
289
112
            ("use",                 create_use,                   Default),
290
            /* ("view",             ), */
291
            /* ("vkern",            ), */
292
        ];
293

            
294
6048
        creators_table.into_iter().map(|(n, c, f)| (n, (c, f))).collect()
295
112
    })
296
1019647
}
297

            
298
impl Element {
299
    /// Takes an XML element name and consumes a list of attribute/value pairs to create an [`Element`].
300
    ///
301
    /// This operation does not fail.  Unknown element names simply produce a [`NonRendering`]
302
    /// element.
303
1024721
    pub fn new(session: &Session, name: &QualName, mut attributes: Attributes) -> Element {
304
2044377
        let (create_fn, flags): (ElementDataCreateFn, ElementCreateFlags) = if name.ns == ns!(svg) {
305
1019663
            match get_element_creators().get(name.local.as_ref()) {
306
                // hack in the SVG namespace for supported element names
307
1017928
                Some(&(create_fn, flags)) => (create_fn, flags),
308

            
309
                // Whenever we encounter a element name we don't understand, represent it as a
310
                // non-rendering element.  This is like a group, but it doesn't do any rendering
311
                // of children.  The effect is that we will ignore all children of unknown elements.
312
1728
                None => (create_non_rendering, ElementCreateFlags::Default),
313
            }
314
        } else {
315
5065
            (create_non_rendering, ElementCreateFlags::Default)
316
        };
317

            
318
1024721
        if flags == ElementCreateFlags::IgnoreClass {
319
197
            attributes.clear_class();
320
        };
321

            
322
1024717
        let element_data = create_fn(session, &attributes);
323

            
324
1024779
        let mut e = Self {
325
1024673
            element_name: name.clone(),
326
1024673
            attributes,
327
1024673
            specified_values: Default::default(),
328
1024673
            important_styles: Default::default(),
329
1024673
            values: Default::default(),
330
1024763
            required_extensions: Default::default(),
331
1024718
            required_features: Default::default(),
332
1024714
            system_language: Default::default(),
333
1024779
            element_data,
334
        };
335

            
336
1024779
        e.set_conditional_processing_attributes(session);
337
1024722
        e.set_presentation_attributes(session);
338

            
339
1024665
        e
340
1024665
    }
341

            
342
2819962
    pub fn element_name(&self) -> &QualName {
343
2819962
        &self.element_name
344
2819962
    }
345

            
346
456
    pub fn get_attributes(&self) -> &Attributes {
347
456
        &self.attributes
348
456
    }
349

            
350
3027053
    pub fn get_id(&self) -> Option<&str> {
351
3027053
        self.attributes.get_id()
352
3027053
    }
353

            
354
924
    pub fn get_class(&self) -> Option<&str> {
355
924
        self.attributes.get_class()
356
924
    }
357

            
358
24630
    pub fn inherit_xml_lang(&mut self, parent: Option<Node>) {
359
24630
        self.specified_values
360
24630
            .inherit_xml_lang(&mut self.values, parent);
361
24630
    }
362

            
363
1470033
    pub fn get_specified_values(&self) -> &SpecifiedValues {
364
        &self.specified_values
365
1470033
    }
366

            
367
1106879
    pub fn get_computed_values(&self) -> &ComputedValues {
368
1106879
        &self.values
369
1106879
    }
370

            
371
24653
    pub fn set_computed_values(&mut self, values: &ComputedValues) {
372
24653
        self.values = values.clone();
373
24653
    }
374

            
375
19
    pub fn get_cond(&self, user_language: &UserLanguage) -> bool {
376
20
        self.required_extensions
377
            .as_ref()
378
1
            .map(|v| v.eval())
379
            .unwrap_or(true)
380
18
            && self
381
                .required_features
382
                .as_ref()
383
2
                .map(|v| v.eval())
384
                .unwrap_or(true)
385
17
            && self
386
                .system_language
387
                .as_ref()
388
11
                .map(|v| v.eval(user_language))
389
                .unwrap_or(true)
390
19
    }
391

            
392
1024720
    fn set_conditional_processing_attributes(&mut self, session: &Session) {
393
1116403
        for (attr, value) in self.attributes.iter() {
394
91683
            match attr.expanded() {
395
1
                expanded_name!("", "requiredExtensions") => {
396
1
                    self.required_extensions = Some(RequiredExtensions::from_attribute(value));
397
                }
398

            
399
2
                expanded_name!("", "requiredFeatures") => {
400
2
                    self.required_features = Some(RequiredFeatures::from_attribute(value));
401
                }
402

            
403
13
                expanded_name!("", "systemLanguage") => {
404
13
                    self.system_language = Some(SystemLanguage::from_attribute(value, session));
405
                }
406

            
407
                _ => {}
408
            }
409
91683
        }
410
1024720
    }
411

            
412
    /// Hands the `attrs` to the node's state, to apply the presentation attributes.
413
1024720
    fn set_presentation_attributes(&mut self, session: &Session) {
414
1024720
        self.specified_values
415
1024720
            .parse_presentation_attributes(session, &self.attributes);
416
1024720
    }
417

            
418
    // Applies a style declaration to the node's specified_values
419
3621
    pub fn apply_style_declaration(&mut self, declaration: &Declaration, origin: Origin) {
420
3621
        self.specified_values.set_property_from_declaration(
421
            declaration,
422
            origin,
423
3621
            &mut self.important_styles,
424
        );
425
3621
    }
426

            
427
    /// Applies CSS styles from the "style" attribute
428
24668
    pub fn set_style_attribute(&mut self, session: &Session) {
429
24668
        let style = self
430
            .attributes
431
            .iter()
432
85699
            .find(|(attr, _)| attr.expanded() == expanded_name!("", "style"))
433
5192
            .map(|(_, value)| value);
434

            
435
24668
        if let Some(style) = style {
436
5189
            self.specified_values.parse_style_declarations(
437
                style,
438
5189
                Origin::Author,
439
5189
                &mut self.important_styles,
440
                session,
441
            );
442
        }
443
24668
    }
444

            
445
    #[rustfmt::skip]
446
820
    pub fn as_filter_effect(&self) -> Option<&dyn FilterEffect> {
447
        use ElementData::*;
448

            
449
820
        match &self.element_data {
450
16
            FeBlend(fe) =>              Some(&**fe),
451
28
            FeColorMatrix(fe) =>        Some(&**fe),
452
28
            FeComponentTransfer(fe) =>  Some(&**fe),
453
76
            FeComposite(fe) =>          Some(&**fe),
454
64
            FeConvolveMatrix(fe) =>     Some(&**fe),
455
96
            FeDiffuseLighting(fe) =>    Some(&**fe),
456
4
            FeDisplacementMap(fe) =>    Some(&**fe),
457
2
            FeDropShadow(fe) =>         Some(&**fe),
458
64
            FeFlood(fe) =>              Some(&**fe),
459
82
            FeGaussianBlur(fe) =>       Some(&**fe),
460
136
            FeImage(fe) =>              Some(&**fe),
461
42
            FeMerge(fe) =>              Some(&**fe),
462
10
            FeMorphology(fe) =>         Some(&**fe),
463
46
            FeOffset(fe) =>             Some(&**fe),
464
78
            FeSpecularLighting(fe) =>   Some(&**fe),
465
4
            FeTile(fe) =>               Some(&**fe),
466
40
            FeTurbulence(fe) =>         Some(&**fe),
467
4
            _ => None,
468
        }
469
820
    }
470

            
471
    /// Returns whether an element of a particular type is only accessed by reference
472
    // from other elements' attributes.  The element could in turn cause other nodes
473
    // to get referenced, potentially causing reference cycles.
474
1001075
    pub fn is_accessed_by_reference(&self) -> bool {
475
        use ElementData::*;
476

            
477
1001075
        matches!(
478
1001075
            self.element_data,
479
            ClipPath(_)
480
                | Filter(_)
481
                | LinearGradient(_)
482
                | Marker(_)
483
                | Mask(_)
484
                | Pattern(_)
485
                | RadialGradient(_)
486
        )
487
1001075
    }
488

            
489
    /// The main drawing function for elements.
490
1958164
    pub fn draw(
491
        &self,
492
        node: &Node,
493
        acquired_nodes: &mut AcquiredNodes<'_>,
494
        cascaded: &CascadedValues<'_>,
495
        viewport: &Viewport,
496
        draw_ctx: &mut DrawingCtx,
497
        clipping: bool,
498
    ) -> Result<BoundingBox, InternalRenderingError> {
499
1958164
        let values = cascaded.get();
500
1958164
        if values.is_displayed() {
501
1956053
            self.element_data
502
                .draw(node, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
503
        } else {
504
2111
            Ok(draw_ctx.empty_bbox())
505
        }
506
1958164
    }
507

            
508
    /// The main layout function for elements.
509
    pub fn layout(
510
        &self,
511
        node: &Node,
512
        acquired_nodes: &mut AcquiredNodes<'_>,
513
        cascaded: &CascadedValues<'_>,
514
        viewport: &Viewport,
515
        draw_ctx: &mut DrawingCtx,
516
        clipping: bool,
517
    ) -> Result<Option<Layer>, InternalRenderingError> {
518
        let values = cascaded.get();
519
        if values.is_displayed() {
520
            self.element_data
521
                .layout(node, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
522
        } else {
523
            Ok(None)
524
        }
525
    }
526
}
527

            
528
impl ElementData {
529
    /// Dispatcher for the draw method of concrete element implementations.
530
    #[rustfmt::skip]
531
1957547
    fn draw(
532
        &self,
533
        node: &Node,
534
        acquired_nodes: &mut AcquiredNodes<'_>,
535
        cascaded: &CascadedValues<'_>,
536
        viewport: &Viewport,
537
        draw_ctx: &mut DrawingCtx,
538
        clipping: bool,
539
    ) -> Result<BoundingBox, InternalRenderingError> {
540
        use ElementData::*;
541

            
542
3915094
        let data: &dyn ElementTrait = match self {
543
254
            Circle(d) =>               &**d,
544
            ClipPath(d) =>             &**d,
545
21
            Ellipse(d) =>              &**d,
546
35
            Filter(d) =>               &**d,
547
505865
            Group(d) =>                &**d,
548
111
            Image(d) =>                &**d,
549
129
            Line(d) =>                 &**d,
550
            LinearGradient(d) =>       &**d,
551
3
            Link(d) =>                 &**d,
552
            Marker(d) =>               &**d,
553
            Mask(d) =>                 &**d,
554
649
            NonRendering(d) =>         &**d,
555
1648
            Path(d) =>                 &**d,
556
            Pattern(d) =>              &**d,
557
34
            Polygon(d) =>              &**d,
558
41
            Polyline(d) =>             &**d,
559
            RadialGradient(d) =>       &**d,
560
946292
            Rect(d) =>                 &**d,
561
            Stop(d) =>                 &**d,
562
            Style(d) =>                &**d,
563
1168
            Svg(d) =>                  &**d,
564
10
            Switch(d) =>               &**d,
565
            Symbol(d) =>               &**d,
566
903
            Text(d) =>                 &**d,
567
            Text2(d) =>                 &**d,
568
            TRef(d) =>                 &**d,
569
            TSpan(d) =>                &**d,
570
500384
            Use(d) =>                  &**d,
571

            
572
            FeBlend(d) =>              &**d,
573
            FeColorMatrix(d) =>        &**d,
574
            FeComponentTransfer(d) =>  &**d,
575
            FeComposite(d) =>          &**d,
576
            FeConvolveMatrix(d) =>     &**d,
577
            FeDiffuseLighting(d) =>    &**d,
578
            FeDisplacementMap(d) =>    &**d,
579
            FeDistantLight(d) =>       &**d,
580
            FeDropShadow(d) =>         &**d,
581
            FeFlood(d) =>              &**d,
582
            FeFuncA(d) =>              &**d,
583
            FeFuncB(d) =>              &**d,
584
            FeFuncG(d) =>              &**d,
585
            FeFuncR(d) =>              &**d,
586
            FeGaussianBlur(d) =>       &**d,
587
            FeImage(d) =>              &**d,
588
            FeMerge(d) =>              &**d,
589
            FeMergeNode(d) =>          &**d,
590
            FeMorphology(d) =>         &**d,
591
            FeOffset(d) =>             &**d,
592
            FePointLight(d) =>         &**d,
593
            FeSpecularLighting(d) =>   &**d,
594
            FeSpotLight(d) =>          &**d,
595
            FeTile(d) =>               &**d,
596
            FeTurbulence(d) =>         &**d,
597
        };
598

            
599
1957547
        data.draw(node, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
600
1957547
    }
601

            
602
    /// Dispatcher for the layout method of concrete element implementations.
603
    #[rustfmt::skip]
604
    fn layout(
605
        &self,
606
        node: &Node,
607
        acquired_nodes: &mut AcquiredNodes<'_>,
608
        cascaded: &CascadedValues<'_>,
609
        viewport: &Viewport,
610
        draw_ctx: &mut DrawingCtx,
611
        clipping: bool,
612
    ) -> Result<Option<Layer>, InternalRenderingError> {
613
        use ElementData::*;
614

            
615
        let data: &dyn ElementTrait = match self {
616
            Circle(d) =>               &**d,
617
            ClipPath(d) =>             &**d,
618
            Ellipse(d) =>              &**d,
619
            Filter(d) =>               &**d,
620
            Group(d) =>                &**d,
621
            Image(d) =>                &**d,
622
            Line(d) =>                 &**d,
623
            LinearGradient(d) =>       &**d,
624
            Link(d) =>                 &**d,
625
            Marker(d) =>               &**d,
626
            Mask(d) =>                 &**d,
627
            NonRendering(d) =>         &**d,
628
            Path(d) =>                 &**d,
629
            Pattern(d) =>              &**d,
630
            Polygon(d) =>              &**d,
631
            Polyline(d) =>             &**d,
632
            RadialGradient(d) =>       &**d,
633
            Rect(d) =>                 &**d,
634
            Stop(d) =>                 &**d,
635
            Style(d) =>                &**d,
636
            Svg(d) =>                  &**d,
637
            Switch(d) =>               &**d,
638
            Symbol(d) =>               &**d,
639
            Text(d) =>                 &**d,
640
            Text2(d) =>                 &**d,
641
            TRef(d) =>                 &**d,
642
            TSpan(d) =>                &**d,
643
            Use(d) =>                  &**d,
644

            
645
            FeBlend(d) =>              &**d,
646
            FeColorMatrix(d) =>        &**d,
647
            FeComponentTransfer(d) =>  &**d,
648
            FeComposite(d) =>          &**d,
649
            FeConvolveMatrix(d) =>     &**d,
650
            FeDiffuseLighting(d) =>    &**d,
651
            FeDisplacementMap(d) =>    &**d,
652
            FeDistantLight(d) =>       &**d,
653
            FeDropShadow(d) =>         &**d,
654
            FeFlood(d) =>              &**d,
655
            FeFuncA(d) =>              &**d,
656
            FeFuncB(d) =>              &**d,
657
            FeFuncG(d) =>              &**d,
658
            FeFuncR(d) =>              &**d,
659
            FeGaussianBlur(d) =>       &**d,
660
            FeImage(d) =>              &**d,
661
            FeMerge(d) =>              &**d,
662
            FeMergeNode(d) =>          &**d,
663
            FeMorphology(d) =>         &**d,
664
            FeOffset(d) =>             &**d,
665
            FePointLight(d) =>         &**d,
666
            FeSpecularLighting(d) =>   &**d,
667
            FeSpotLight(d) =>          &**d,
668
            FeTile(d) =>               &**d,
669
            FeTurbulence(d) =>         &**d,
670
        };
671

            
672
        data.layout(node, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
673
    }
674
}
675

            
676
macro_rules! e {
677
    ($name:ident, $element_type:ident) => {
678
1024722
        pub fn $name(session: &Session, attributes: &Attributes) -> ElementData {
679
1024722
            let mut payload = Box::<$element_type>::default();
680
1024722
            payload.set_attributes(attributes, session);
681

            
682
1024722
            ElementData::$element_type(payload)
683
1024722
        }
684
    };
685
}
686

            
687
#[rustfmt::skip]
688
mod creators {
689
    use super::*;
690

            
691
    e!(create_circle,                   Circle);
692
    e!(create_clip_path,                ClipPath);
693
    e!(create_defs,                     NonRendering);
694
    e!(create_ellipse,                  Ellipse);
695
    e!(create_fe_blend,                 FeBlend);
696
    e!(create_fe_color_matrix,          FeColorMatrix);
697
    e!(create_fe_component_transfer,    FeComponentTransfer);
698
    e!(create_fe_func_a,                FeFuncA);
699
    e!(create_fe_func_b,                FeFuncB);
700
    e!(create_fe_func_g,                FeFuncG);
701
    e!(create_fe_func_r,                FeFuncR);
702
    e!(create_fe_composite,             FeComposite);
703
    e!(create_fe_convolve_matrix,       FeConvolveMatrix);
704
    e!(create_fe_diffuse_lighting,      FeDiffuseLighting);
705
    e!(create_fe_displacement_map,      FeDisplacementMap);
706
    e!(create_fe_distant_light,         FeDistantLight);
707
    e!(create_fe_drop_shadow,           FeDropShadow);
708
    e!(create_fe_flood,                 FeFlood);
709
    e!(create_fe_gaussian_blur,         FeGaussianBlur);
710
    e!(create_fe_image,                 FeImage);
711
    e!(create_fe_merge,                 FeMerge);
712
    e!(create_fe_merge_node,            FeMergeNode);
713
    e!(create_fe_morphology,            FeMorphology);
714
    e!(create_fe_offset,                FeOffset);
715
    e!(create_fe_point_light,           FePointLight);
716
    e!(create_fe_specular_lighting,     FeSpecularLighting);
717
    e!(create_fe_spot_light,            FeSpotLight);
718
    e!(create_fe_tile,                  FeTile);
719
    e!(create_fe_turbulence,            FeTurbulence);
720
    e!(create_filter,                   Filter);
721
    e!(create_group,                    Group);
722
    e!(create_image,                    Image);
723
    e!(create_line,                     Line);
724
    e!(create_linear_gradient,          LinearGradient);
725
    e!(create_link,                     Link);
726
    e!(create_marker,                   Marker);
727
    e!(create_mask,                     Mask);
728
    e!(create_non_rendering,            NonRendering);
729
    e!(create_path,                     Path);
730
    e!(create_pattern,                  Pattern);
731
    e!(create_polygon,                  Polygon);
732
    e!(create_polyline,                 Polyline);
733
    e!(create_radial_gradient,          RadialGradient);
734
    e!(create_rect,                     Rect);
735
    e!(create_stop,                     Stop);
736
    e!(create_style,                    Style);
737
    e!(create_svg,                      Svg);
738
    e!(create_switch,                   Switch);
739
    e!(create_symbol,                   Symbol);
740
    e!(create_text,                     Text);
741
    e!(create_text2,                    Text2);
742
    e!(create_tref,                     TRef);
743
    e!(create_tspan,                    TSpan);
744
    e!(create_use,                      Use);
745

            
746
    /* Hack to make multiImage sort-of work
747
     *
748
     * disabled for now, as markup5ever doesn't have local names for
749
     * multiImage, subImage, subImageRef.  Maybe we can just... create them ourselves?
750
     *
751
     * Is multiImage even in SVG2?
752
     */
753
    /*
754
    e!(create_multi_image,              Switch);
755
    e!(create_sub_image,                Group);
756
    e!(create_sub_image_ref,            Image);
757
    */
758
}
759

            
760
use creators::*;
761

            
762
type ElementDataCreateFn = fn(session: &Session, attributes: &Attributes) -> ElementData;
763

            
764
1024700
#[derive(Copy, Clone, PartialEq)]
765
enum ElementCreateFlags {
766
    Default,
767
    IgnoreClass,
768
}
769

            
770
static ELEMENT_CREATORS: OnceLock<
771
    HashMap<&'static str, (ElementDataCreateFn, ElementCreateFlags)>,
772
> = OnceLock::new();