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
1022267
    pub fn new_element(session: &Session, name: &QualName, attrs: Attributes) -> NodeData {
72
1022267
        NodeData::Element(Box::new(Element::new(session, name, attrs)))
73
1022267
    }
74

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

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

            
91
406
        Ok(())
92
406
    }
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
1459493
    pub fn clone_with_node(&self, node: &'a Node) -> CascadedValues<'a> {
123
1459493
        match self.inner {
124
514863
            CascadedInner::FromNode(_) => CascadedValues {
125
514863
                inner: CascadedInner::FromNode(node.borrow_element()),
126
514863
                context_fill: self.context_fill.clone(),
127
514863
                context_stroke: self.context_stroke.clone(),
128
514863
            },
129

            
130
944630
            CascadedInner::FromValues(ref v) => CascadedValues::new_from_values(
131
                node,
132
944630
                v,
133
944630
                self.context_fill.clone(),
134
944630
                self.context_stroke.clone(),
135
944630
            ),
136
        }
137
1459493
    }
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
53714
    pub fn new_from_node(node: &Node) -> CascadedValues<'_> {
145
53714
        CascadedValues {
146
53714
            inner: CascadedInner::FromNode(node.borrow_element()),
147
53714
            context_fill: None,
148
53714
            context_stroke: None,
149
        }
150
53714
    }
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
1444810
    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
1444810
        let mut v = Box::new(values.clone());
164
1444810
        node.borrow_element()
165
            .get_specified_values()
166
1444810
            .to_computed_values(&mut v);
167

            
168
1444810
        CascadedValues {
169
1444810
            inner: CascadedInner::FromValues(v),
170
1444810
            context_fill: fill,
171
1444810
            context_stroke: stroke,
172
        }
173
1444810
    }
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
3972206
    pub fn get(&'a self) -> &'a ComputedValues {
180
7944412
        match self.inner {
181
1082596
            CascadedInner::FromNode(ref e) => e.get_computed_values(),
182
2889610
            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
3972206
    }
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
5063756
    fn is_element(&self) -> bool {
225
5063756
        matches!(*self.borrow(), NodeData::Element(_))
226
5063756
    }
227

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

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

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

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

            
253
504673
    fn borrow_element_data(&self) -> Ref<'_, ElementData> {
254
1009345
        Ref::map(self.borrow(), |n| match n {
255
504672
            NodeData::Element(e) => &e.element_data,
256
            _ => panic!("tried to borrow_element_data for a non-element node"),
257
504672
        })
258
504673
    }
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
1834
        std::cell::Ref::map($node.borrow_element_data(), |d| match d {
277
1834
            $crate::element::ElementData::$element_type(ref e) => &*e,
278
            _ => panic!("tried to borrow_element_as {}", stringify!($element_type)),
279
1834
        })
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
22231
    fn cascade(&mut self, values: &ComputedValues) {
290
22249
        let mut values = values.clone();
291

            
292
        {
293
22231
            let mut elt = self.borrow_element_mut();
294

            
295
22240
            elt.get_specified_values().to_computed_values(&mut values);
296
22234
            elt.set_computed_values(&values);
297
22228
        }
298

            
299
74847
        for mut child in self.children().filter(|c| c.is_element()) {
300
21134
            child.cascade(&values);
301
21134
        }
302
20067
    }
303
}
304

            
305
/// Helper trait for drawing recursively.
306
///
307
/// This is a trait because [`Node`] is a type alias over [`rctree::Node`], not a concrete type.
308
pub trait NodeDraw {
309
    fn draw(
310
        &self,
311
        acquired_nodes: &mut AcquiredNodes<'_>,
312
        cascaded: &CascadedValues<'_>,
313
        viewport: &Viewport,
314
        draw_ctx: &mut DrawingCtx,
315
        clipping: bool,
316
    ) -> Result<BoundingBox, InternalRenderingError>;
317

            
318
    fn draw_children(
319
        &self,
320
        acquired_nodes: &mut AcquiredNodes<'_>,
321
        cascaded: &CascadedValues<'_>,
322
        viewport: &Viewport,
323
        draw_ctx: &mut DrawingCtx,
324
        clipping: bool,
325
    ) -> Result<BoundingBox, InternalRenderingError>;
326
}
327

            
328
impl NodeDraw for Node {
329
1958481
    fn draw(
330
        &self,
331
        acquired_nodes: &mut AcquiredNodes<'_>,
332
        cascaded: &CascadedValues<'_>,
333
        viewport: &Viewport,
334
        draw_ctx: &mut DrawingCtx,
335
        clipping: bool,
336
    ) -> Result<BoundingBox, InternalRenderingError> {
337
1958481
        match *self.borrow() {
338
1957972
            NodeData::Element(ref e) => {
339
1957972
                rsvg_log!(draw_ctx.session(), "({}", e);
340
1957821
                let res = match e.draw(self, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
341
                {
342
1957425
                    Ok(bbox) => Ok(bbox),
343

            
344
                    // https://www.w3.org/TR/css-transforms-1/#transform-function-lists
345
                    //
346
                    // "If a transform function causes the current transformation matrix of an
347
                    // object to be non-invertible, the object and its content do not get
348
                    // displayed."
349
2
                    Err(InternalRenderingError::InvalidTransform) => Ok(draw_ctx.empty_bbox()),
350

            
351
36
                    Err(e) => Err(e),
352
1957463
                };
353

            
354
1957461
                rsvg_log!(draw_ctx.session(), ")");
355

            
356
1957031
                res
357
1957031
            }
358

            
359
            _ => Ok(draw_ctx.empty_bbox()),
360
        }
361
1957031
    }
362

            
363
3477355
    fn draw_children(
364
        &self,
365
        acquired_nodes: &mut AcquiredNodes<'_>,
366
        cascaded: &CascadedValues<'_>,
367
        viewport: &Viewport,
368
        draw_ctx: &mut DrawingCtx,
369
        clipping: bool,
370
    ) -> Result<BoundingBox, InternalRenderingError> {
371
3477355
        let mut bbox = draw_ctx.empty_bbox();
372

            
373
6939640
        for child in self.children().filter(|c| c.is_element()) {
374
1457890
            let child_bbox = draw_ctx.draw_node_from_stack(
375
                &child,
376
                acquired_nodes,
377
1461310
                &CascadedValues::clone_with_node(cascaded, &child),
378
                viewport,
379
                clipping,
380
1457866
            )?;
381
1461625
            bbox.insert(&child_bbox);
382
1459244
        }
383

            
384
556819
        Ok(bbox)
385
556837
    }
386
}