1
//! Tree nodes, the representation of SVG elements.
2
//!
3
//! Librsvg uses the [rctree crate][rctree] to represent the SVG tree of elements.
4
//! Its [`rctree::Node`] struct provides a generic wrapper over nodes in a tree.
5
//! Librsvg puts a [`NodeData`] as the type parameter of [`rctree::Node`].  For convenience,
6
//! librsvg has a type alias [`Node`]` = rctree::Node<NodeData>`.
7
//!
8
//! Nodes are not constructed directly by callers;
9

            
10
use markup5ever::QualName;
11
use std::cell::{Ref, RefMut};
12
use std::fmt;
13
use std::rc::Rc;
14

            
15
use crate::bbox::BoundingBox;
16
use crate::document::AcquiredNodes;
17
use crate::drawing_ctx::{DrawingCtx, Viewport};
18
use crate::element::*;
19
use crate::error::*;
20
use crate::paint_server::PaintSource;
21
use crate::properties::ComputedValues;
22
use crate::rsvg_log;
23
use crate::session::Session;
24
use crate::text::Chars;
25
use crate::xml::Attributes;
26

            
27
/// Strong reference to an element in the SVG tree.
28
///
29
/// See the [module documentation][self] for more information.
30
pub type Node = rctree::Node<NodeData>;
31

            
32
/// Weak reference to an element in the SVG tree.
33
///
34
/// See the [module documentation][self] for more information.
35
pub type WeakNode = rctree::WeakNode<NodeData>;
36

            
37
/// Data for a single DOM node.
38
///
39
/// ## Memory consumption
40
///
41
/// SVG files look like this, roughly:
42
///
43
/// ```xml
44
/// <svg>
45
///   <rect x="10" y="20"/>
46
///   <path d="..."/>
47
///   <text x="10" y="20">Hello</text>
48
///   <!-- etc -->
49
/// </svg>
50
/// ```
51
///
52
/// Each element has a bunch of data, including the styles, which is
53
/// the biggest consumer of memory within the `Element` struct.  But
54
/// between each element there is a text node; in the example above
55
/// there are a bunch of text nodes with just whitespace (newlines and
56
/// spaces), and a single text node with "`Hello`" in it from the
57
/// `<text>` element.
58
///
59
/// ## Accessing the node's contents
60
///
61
/// Code that traverses the DOM tree needs to find out at runtime what
62
/// each node stands for.  First, use the `is_chars` or `is_element`
63
/// methods from the `NodeBorrow` trait to see if you can then call
64
/// `borrow_chars`, `borrow_element`, or `borrow_element_mut`.
65
pub enum NodeData {
66
    Element(Box<Element>),
67
    Text(Box<Chars>),
68
}
69

            
70
impl NodeData {
71
1024722
    pub fn new_element(session: &Session, name: &QualName, attrs: Attributes) -> NodeData {
72
1024722
        NodeData::Element(Box::new(Element::new(session, name, attrs)))
73
1024722
    }
74

            
75
1034035
    pub fn new_chars(initial_text: &str) -> NodeData {
76
1034035
        NodeData::Text(Box::new(Chars::new(initial_text)))
77
1034035
    }
78
}
79

            
80
impl fmt::Display for NodeData {
81
408
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82
408
        match *self {
83
408
            NodeData::Element(ref e) => {
84
408
                write!(f, "{e}")?;
85
            }
86
            NodeData::Text(_) => {
87
408
                write!(f, "Chars")?;
88
            }
89
        }
90

            
91
408
        Ok(())
92
408
    }
93
}
94

            
95
/// Can obtain computed values from a node
96
///
97
/// In our tree of SVG elements (Node in our parlance), each node stores a `ComputedValues` that
98
/// gets computed during the initial CSS cascade.  However, sometimes nodes need to be rendered
99
/// outside the normal hierarchy.  For example, the `<use>` element can "instance" a subtree from
100
/// elsewhere in the SVG; it causes the instanced subtree to re-cascade from the computed values for
101
/// the `<use>` element.
102
///
103
/// You can then call the `get()` method on the resulting `CascadedValues` to get a
104
/// `&ComputedValues` whose fields you can access.
105
pub struct CascadedValues<'a> {
106
    inner: CascadedInner<'a>,
107
    pub context_stroke: Option<Rc<PaintSource>>,
108
    pub context_fill: Option<Rc<PaintSource>>,
109
}
110

            
111
enum CascadedInner<'a> {
112
    FromNode(Ref<'a, Element>),
113
    FromValues(Box<ComputedValues>),
114
}
115

            
116
impl<'a> CascadedValues<'a> {
117
    /// Creates a `CascadedValues` that has the same cascading mode as &self
118
    ///
119
    /// This is what nodes should normally use to draw their children from their `draw()` method.
120
    /// Nodes that need to override the cascade for their children can use `new_from_values()`
121
    /// instead.
122
1459969
    pub fn clone_with_node(&self, node: &'a Node) -> CascadedValues<'a> {
123
1459969
        match self.inner {
124
514832
            CascadedInner::FromNode(_) => CascadedValues {
125
514832
                inner: CascadedInner::FromNode(node.borrow_element()),
126
514832
                context_fill: self.context_fill.clone(),
127
514832
                context_stroke: self.context_stroke.clone(),
128
514832
            },
129

            
130
945137
            CascadedInner::FromValues(ref v) => CascadedValues::new_from_values(
131
                node,
132
945137
                v,
133
945137
                self.context_fill.clone(),
134
945137
                self.context_stroke.clone(),
135
945137
            ),
136
        }
137
1459969
    }
138

            
139
    /// Creates a `CascadedValues` that will hold the `node`'s computed values
140
    ///
141
    /// This is to be used only in the toplevel drawing function, or in elements like `<marker>`
142
    /// that don't propagate their parent's cascade to their children.  All others should use
143
    /// `new()` to derive the cascade from an existing one.
144
53743
    pub fn new_from_node(node: &Node) -> CascadedValues<'_> {
145
53743
        CascadedValues {
146
53743
            inner: CascadedInner::FromNode(node.borrow_element()),
147
53743
            context_fill: None,
148
53743
            context_stroke: None,
149
        }
150
53743
    }
151

            
152
    /// Creates a `CascadedValues` that will override the `node`'s cascade with the specified
153
    /// `values`
154
    ///
155
    /// This is for the `<use>` element, which draws the element which it references with the
156
    /// `<use>`'s own cascade, not with the element's original cascade.
157
1445379
    pub fn new_from_values(
158
        node: &'a Node,
159
        values: &ComputedValues,
160
        fill: Option<Rc<PaintSource>>,
161
        stroke: Option<Rc<PaintSource>>,
162
    ) -> CascadedValues<'a> {
163
1445379
        let mut v = Box::new(values.clone());
164
1445379
        node.borrow_element()
165
            .get_specified_values()
166
1445379
            .to_computed_values(&mut v);
167

            
168
1445379
        CascadedValues {
169
1445379
            inner: CascadedInner::FromValues(v),
170
1445379
            context_fill: fill,
171
1445379
            context_stroke: stroke,
172
        }
173
1445379
    }
174

            
175
    /// Returns the cascaded `ComputedValues`.
176
    ///
177
    /// Nodes should use this from their `Draw::draw()` implementation to get the
178
    /// `ComputedValues` from the `CascadedValues` that got passed to `draw()`.
179
3973372
    pub fn get(&'a self) -> &'a ComputedValues {
180
7946744
        match self.inner {
181
1082595
            CascadedInner::FromNode(ref e) => e.get_computed_values(),
182
2890777
            CascadedInner::FromValues(ref v) => v,
183
        }
184

            
185
        // if values.fill == "context-fill" {
186
        //     values.fill=self.context_fill
187
        // }
188
        // if values.stroke == "context-stroke" {
189
        //     values.stroke=self.context_stroke
190
        // }
191
3973372
    }
192
}
193

            
194
/// Helper trait to get different NodeData variants
195
pub trait NodeBorrow {
196
    /// Returns `false` for NodeData::Text, `true` otherwise.
197
    fn is_element(&self) -> bool;
198

            
199
    /// Returns `true` for NodeData::Text, `false` otherwise.
200
    fn is_chars(&self) -> bool;
201

            
202
    /// Borrows a `Chars` reference.
203
    ///
204
    /// Panics: will panic if `&self` is not a `NodeData::Text` node
205
    fn borrow_chars(&self) -> Ref<'_, Chars>;
206

            
207
    /// Borrows an `Element` reference
208
    ///
209
    /// Panics: will panic if `&self` is not a `NodeData::Element` node
210
    fn borrow_element(&self) -> Ref<'_, Element>;
211

            
212
    /// Borrows an `Element` reference mutably
213
    ///
214
    /// Panics: will panic if `&self` is not a `NodeData::Element` node
215
    fn borrow_element_mut(&mut self) -> RefMut<'_, Element>;
216

            
217
    /// Borrows an `ElementData` reference to the concrete element type.
218
    ///
219
    /// Panics: will panic if `&self` is not a `NodeData::Element` node
220
    fn borrow_element_data(&self) -> Ref<'_, ElementData>;
221
}
222

            
223
impl NodeBorrow for Node {
224
5086067
    fn is_element(&self) -> bool {
225
5086067
        matches!(*self.borrow(), NodeData::Element(_))
226
5086067
    }
227

            
228
1025755
    fn is_chars(&self) -> bool {
229
1025755
        matches!(*self.borrow(), NodeData::Text(_))
230
1025755
    }
231

            
232
3602
    fn borrow_chars(&self) -> Ref<'_, Chars> {
233
7203
        Ref::map(self.borrow(), |n| match n {
234
3601
            NodeData::Text(c) => &**c,
235
            _ => panic!("tried to borrow_chars for a non-text node"),
236
3601
        })
237
3602
    }
238

            
239
7852098
    fn borrow_element(&self) -> Ref<'_, Element> {
240
15692517
        Ref::map(self.borrow(), |n| match n {
241
7840419
            NodeData::Element(e) => &**e,
242
            _ => panic!("tried to borrow_element for a non-element node"),
243
7840419
        })
244
7852098
    }
245

            
246
73976
    fn borrow_element_mut(&mut self) -> RefMut<'_, Element> {
247
147849
        RefMut::map(self.borrow_mut(), |n| match &mut *n {
248
73873
            NodeData::Element(e) => &mut **e,
249
            _ => panic!("tried to borrow_element_mut for a non-element node"),
250
73873
        })
251
73976
    }
252

            
253
504674
    fn borrow_element_data(&self) -> Ref<'_, ElementData> {
254
1009347
        Ref::map(self.borrow(), |n| match n {
255
504673
            NodeData::Element(e) => &e.element_data,
256
            _ => panic!("tried to borrow_element_data for a non-element node"),
257
504673
        })
258
504674
    }
259
}
260

            
261
#[doc(hidden)]
262
#[macro_export]
263
macro_rules! is_element_of_type {
264
    ($node:expr, $element_type:ident) => {
265
        matches!(
266
            $node.borrow_element().element_data,
267
            $crate::element::ElementData::$element_type(_)
268
        )
269
    };
270
}
271

            
272
#[doc(hidden)]
273
#[macro_export]
274
macro_rules! borrow_element_as {
275
    ($node:expr, $element_type:ident) => {
276
1852
        std::cell::Ref::map($node.borrow_element_data(), |d| match d {
277
1852
            $crate::element::ElementData::$element_type(ref e) => &*e,
278
            _ => panic!("tried to borrow_element_as {}", stringify!($element_type)),
279
1852
        })
280
    };
281
}
282

            
283
/// Helper trait for cascading recursively
284
pub trait NodeCascade {
285
    fn cascade(&mut self, values: &ComputedValues);
286
}
287

            
288
impl NodeCascade for Node {
289
24645
    fn cascade(&mut self, values: &ComputedValues) {
290
        // We box this because ComputedValues is a big structure.  Since this function is
291
        // recursive, we want to minimize stack consumption during recursion.
292
        //
293
        // As of 2024/Oct/24, the unboxed versions uses 1792 bytes of stack between each
294
        // recursive call to cascade(); with the boxed version it is just 8 bytes.
295
        //
296
        // We should probably change this to a non-recursive tree traversal at some point.
297

            
298
24681
        let mut values = Box::new(values.clone());
299

            
300
        {
301
24645
            let mut elt = self.borrow_element_mut();
302

            
303
24662
            elt.get_specified_values().to_computed_values(&mut values);
304
24669
            elt.set_computed_values(&values);
305
24624
        }
306

            
307
82123
        for mut child in self.children().filter(|c| c.is_element()) {
308
23551
            child.cascade(&values);
309
48171
        }
310
22523
    }
311
}
312

            
313
/// Helper trait for drawing recursively.
314
///
315
/// This is a trait because [`Node`] is a type alias over [`rctree::Node`], not a concrete type.
316
pub trait NodeDraw {
317
    fn draw(
318
        &self,
319
        acquired_nodes: &mut AcquiredNodes<'_>,
320
        cascaded: &CascadedValues<'_>,
321
        viewport: &Viewport,
322
        draw_ctx: &mut DrawingCtx,
323
        clipping: bool,
324
    ) -> Result<BoundingBox, InternalRenderingError>;
325

            
326
    fn draw_children(
327
        &self,
328
        acquired_nodes: &mut AcquiredNodes<'_>,
329
        cascaded: &CascadedValues<'_>,
330
        viewport: &Viewport,
331
        draw_ctx: &mut DrawingCtx,
332
        clipping: bool,
333
    ) -> Result<BoundingBox, InternalRenderingError>;
334
}
335

            
336
impl NodeDraw for Node {
337
1959345
    fn draw(
338
        &self,
339
        acquired_nodes: &mut AcquiredNodes<'_>,
340
        cascaded: &CascadedValues<'_>,
341
        viewport: &Viewport,
342
        draw_ctx: &mut DrawingCtx,
343
        clipping: bool,
344
    ) -> Result<BoundingBox, InternalRenderingError> {
345
1959345
        match *self.borrow() {
346
1958900
            NodeData::Element(ref e) => {
347
1958900
                rsvg_log!(draw_ctx.session(), "({}", e);
348
1958756
                let res = match e.draw(self, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
349
                {
350
1957984
                    Ok(bbox) => Ok(bbox),
351

            
352
                    // https://www.w3.org/TR/css-transforms-1/#transform-function-lists
353
                    //
354
                    // "If a transform function causes the current transformation matrix of an
355
                    // object to be non-invertible, the object and its content do not get
356
                    // displayed."
357
2
                    Err(InternalRenderingError::InvalidTransform) => Ok(draw_ctx.empty_bbox()),
358

            
359
279
                    Err(InternalRenderingError::CircularReference(node)) => {
360
279
                        if node != *self {
361
139
                            return Ok(draw_ctx.empty_bbox());
362
                        } else {
363
140
                            return Err(InternalRenderingError::CircularReference(node));
364
                        }
365
279
                    }
366

            
367
190
                    Err(e) => Err(e),
368
1958455
                };
369

            
370
1958176
                rsvg_log!(draw_ctx.session(), ")");
371

            
372
1958040
                res
373
1958040
            }
374

            
375
            _ => Ok(draw_ctx.empty_bbox()),
376
        }
377
1958319
    }
378

            
379
3475729
    fn draw_children(
380
        &self,
381
        acquired_nodes: &mut AcquiredNodes<'_>,
382
        cascaded: &CascadedValues<'_>,
383
        viewport: &Viewport,
384
        draw_ctx: &mut DrawingCtx,
385
        clipping: bool,
386
    ) -> Result<BoundingBox, InternalRenderingError> {
387
3475729
        let mut bbox = draw_ctx.empty_bbox();
388

            
389
6944084
        for child in self.children().filter(|c| c.is_element()) {
390
1458522
            let child_bbox = draw_ctx.draw_node_from_stack(
391
                &child,
392
                acquired_nodes,
393
1459625
                &CascadedValues::clone_with_node(cascaded, &child),
394
                viewport,
395
                clipping,
396
1458428
            )?;
397
1459818
            bbox.insert(&child_bbox);
398
2016392
        }
399

            
400
556861
        Ok(bbox)
401
557149
    }
402
}