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::xml::Attributes;
49

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

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

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

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

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

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

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

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

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

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

            
291
5936
        creators_table.into_iter().map(|(n, c, f)| (n, (c, f))).collect()
292
112
    })
293
1019645
}
294

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

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

            
315
1024724
        if flags == ElementCreateFlags::IgnoreClass {
316
197
            attributes.clear_class();
317
        };
318

            
319
1024720
        let element_data = create_fn(session, &attributes);
320

            
321
1024769
        let mut e = Self {
322
1024691
            element_name: name.clone(),
323
1024691
            attributes,
324
1024691
            specified_values: Default::default(),
325
1024691
            important_styles: Default::default(),
326
1024691
            values: Default::default(),
327
1024761
            required_extensions: Default::default(),
328
1024726
            required_features: Default::default(),
329
1024722
            system_language: Default::default(),
330
1024769
            element_data,
331
        };
332

            
333
1024769
        e.set_conditional_processing_attributes(session);
334
1024726
        e.set_presentation_attributes(session);
335

            
336
1024683
        e
337
1024683
    }
338

            
339
2813961
    pub fn element_name(&self) -> &QualName {
340
2813961
        &self.element_name
341
2813961
    }
342

            
343
456
    pub fn get_attributes(&self) -> &Attributes {
344
456
        &self.attributes
345
456
    }
346

            
347
3026663
    pub fn get_id(&self) -> Option<&str> {
348
3026663
        self.attributes.get_id()
349
3026663
    }
350

            
351
925
    pub fn get_class(&self) -> Option<&str> {
352
925
        self.attributes.get_class()
353
925
    }
354

            
355
24657
    pub fn inherit_xml_lang(&mut self, parent: Option<Node>) {
356
24657
        self.specified_values
357
24657
            .inherit_xml_lang(&mut self.values, parent);
358
24657
    }
359

            
360
1470024
    pub fn get_specified_values(&self) -> &SpecifiedValues {
361
        &self.specified_values
362
1470024
    }
363

            
364
1106858
    pub fn get_computed_values(&self) -> &ComputedValues {
365
1106858
        &self.values
366
1106858
    }
367

            
368
24665
    pub fn set_computed_values(&mut self, values: &ComputedValues) {
369
24665
        self.values = values.clone();
370
24665
    }
371

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

            
389
1024729
    fn set_conditional_processing_attributes(&mut self, session: &Session) {
390
1116386
        for (attr, value) in self.attributes.iter() {
391
91657
            match attr.expanded() {
392
1
                expanded_name!("", "requiredExtensions") => {
393
1
                    self.required_extensions = Some(RequiredExtensions::from_attribute(value));
394
                }
395

            
396
2
                expanded_name!("", "requiredFeatures") => {
397
2
                    self.required_features = Some(RequiredFeatures::from_attribute(value));
398
                }
399

            
400
13
                expanded_name!("", "systemLanguage") => {
401
13
                    self.system_language = Some(SystemLanguage::from_attribute(value, session));
402
                }
403

            
404
                _ => {}
405
            }
406
91657
        }
407
1024729
    }
408

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

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

            
424
    /// Applies CSS styles from the "style" attribute
425
24664
    pub fn set_style_attribute(&mut self, session: &Session) {
426
24664
        let style = self
427
            .attributes
428
            .iter()
429
85638
            .find(|(attr, _)| attr.expanded() == expanded_name!("", "style"))
430
5191
            .map(|(_, value)| value);
431

            
432
24664
        if let Some(style) = style {
433
5185
            self.specified_values.parse_style_declarations(
434
                style,
435
5185
                Origin::Author,
436
5185
                &mut self.important_styles,
437
                session,
438
            );
439
        }
440
24664
    }
441

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

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

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

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

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

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

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

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

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

            
595
1957317
        data.draw(node, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
596
1957317
    }
597

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

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

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

            
667
        data.layout(node, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
668
    }
669
}
670

            
671
macro_rules! e {
672
    ($name:ident, $element_type:ident) => {
673
1024731
        pub fn $name(session: &Session, attributes: &Attributes) -> ElementData {
674
1024731
            let mut payload = Box::<$element_type>::default();
675
1024731
            payload.set_attributes(attributes, session);
676

            
677
1024731
            ElementData::$element_type(payload)
678
1024731
        }
679
    };
680
}
681

            
682
#[rustfmt::skip]
683
mod creators {
684
    use super::*;
685

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

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

            
754
use creators::*;
755

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

            
758
1024697
#[derive(Copy, Clone, PartialEq)]
759
enum ElementCreateFlags {
760
    Default,
761
    IgnoreClass,
762
}
763

            
764
static ELEMENT_CREATORS: OnceLock<
765
    HashMap<&'static str, (ElementDataCreateFn, ElementCreateFlags)>,
766
> = OnceLock::new();