1use markup5ever::QualName;
11use std::cell::{Ref, RefMut};
12use std::fmt;
13use std::rc::Rc;
14
15use crate::document::AcquiredNodes;
16use crate::drawing_ctx::{DrawingCtx, Viewport};
17use crate::element::*;
18use crate::error::*;
19use crate::paint_server::PaintSource;
20use crate::properties::ComputedValues;
21use crate::rsvg_log;
22use crate::session::Session;
23use crate::text::Chars;
24use crate::xml::Attributes;
25
26pub type Node = rctree::Node<NodeData>;
30
31pub type WeakNode = rctree::WeakNode<NodeData>;
35
36pub enum NodeData {
65 Element(Box<Element>),
66 Text(Box<Chars>),
67}
68
69impl NodeData {
70 pub fn new_element(session: &Session, name: &QualName, attrs: Attributes) -> NodeData {
71 NodeData::Element(Box::new(Element::new(session, name, attrs)))
72 }
73
74 pub fn new_chars(initial_text: &str) -> NodeData {
75 NodeData::Text(Box::new(Chars::new(initial_text)))
76 }
77}
78
79impl fmt::Display for NodeData {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 match *self {
82 NodeData::Element(ref e) => {
83 write!(f, "{e}")?;
84 }
85 NodeData::Text(_) => {
86 write!(f, "Chars")?;
87 }
88 }
89
90 Ok(())
91 }
92}
93
94pub struct CascadedValues<'a> {
105 inner: CascadedInner<'a>,
106 pub context_stroke: Option<Rc<PaintSource>>,
107 pub context_fill: Option<Rc<PaintSource>>,
108}
109
110enum CascadedInner<'a> {
111 FromNode(Ref<'a, Element>),
112 FromValues(Box<ComputedValues>),
113}
114
115impl<'a> CascadedValues<'a> {
116 pub fn clone_with_node(&self, node: &'a Node) -> CascadedValues<'a> {
122 match self.inner {
123 CascadedInner::FromNode(_) => CascadedValues {
124 inner: CascadedInner::FromNode(node.borrow_element()),
125 context_fill: self.context_fill.clone(),
126 context_stroke: self.context_stroke.clone(),
127 },
128
129 CascadedInner::FromValues(ref v) => CascadedValues::new_from_values(
130 node,
131 v,
132 self.context_fill.clone(),
133 self.context_stroke.clone(),
134 ),
135 }
136 }
137
138 pub fn new_from_node(node: &Node) -> CascadedValues<'_> {
144 CascadedValues {
145 inner: CascadedInner::FromNode(node.borrow_element()),
146 context_fill: None,
147 context_stroke: None,
148 }
149 }
150
151 pub fn new_from_values(
157 node: &'a Node,
158 values: &ComputedValues,
159 fill: Option<Rc<PaintSource>>,
160 stroke: Option<Rc<PaintSource>>,
161 ) -> CascadedValues<'a> {
162 let mut v = Box::new(values.clone());
163 node.borrow_element()
164 .get_specified_values()
165 .to_computed_values(&mut v);
166
167 CascadedValues {
168 inner: CascadedInner::FromValues(v),
169 context_fill: fill,
170 context_stroke: stroke,
171 }
172 }
173
174 pub fn get(&'a self) -> &'a ComputedValues {
179 match self.inner {
180 CascadedInner::FromNode(ref e) => e.get_computed_values(),
181 CascadedInner::FromValues(ref v) => v,
182 }
183
184 }
191}
192
193pub trait NodeBorrow {
195 fn is_element(&self) -> bool;
197
198 fn is_chars(&self) -> bool;
200
201 fn borrow_chars(&self) -> Ref<'_, Chars>;
205
206 fn borrow_element(&self) -> Ref<'_, Element>;
210
211 fn borrow_element_mut(&mut self) -> RefMut<'_, Element>;
215
216 fn borrow_element_data(&self) -> Ref<'_, ElementData>;
220}
221
222impl NodeBorrow for Node {
223 fn is_element(&self) -> bool {
224 matches!(*self.borrow(), NodeData::Element(_))
225 }
226
227 fn is_chars(&self) -> bool {
228 matches!(*self.borrow(), NodeData::Text(_))
229 }
230
231 fn borrow_chars(&self) -> Ref<'_, Chars> {
232 Ref::map(self.borrow(), |n| match n {
233 NodeData::Text(c) => &**c,
234 _ => panic!("tried to borrow_chars for a non-text node"),
235 })
236 }
237
238 fn borrow_element(&self) -> Ref<'_, Element> {
239 Ref::map(self.borrow(), |n| match n {
240 NodeData::Element(e) => &**e,
241 _ => panic!("tried to borrow_element for a non-element node"),
242 })
243 }
244
245 fn borrow_element_mut(&mut self) -> RefMut<'_, Element> {
246 RefMut::map(self.borrow_mut(), |n| match &mut *n {
247 NodeData::Element(e) => &mut **e,
248 _ => panic!("tried to borrow_element_mut for a non-element node"),
249 })
250 }
251
252 fn borrow_element_data(&self) -> Ref<'_, ElementData> {
253 Ref::map(self.borrow(), |n| match n {
254 NodeData::Element(e) => &e.element_data,
255 _ => panic!("tried to borrow_element_data for a non-element node"),
256 })
257 }
258}
259
260#[doc(hidden)]
261#[macro_export]
262macro_rules! is_element_of_type {
263 ($node:expr, $element_type:ident) => {
264 matches!(
265 $node.borrow_element().element_data,
266 $crate::element::ElementData::$element_type(_)
267 )
268 };
269}
270
271#[doc(hidden)]
272#[macro_export]
273macro_rules! borrow_element_as {
274 ($node:expr, $element_type:ident) => {
275 std::cell::Ref::map($node.borrow_element_data(), |d| match d {
276 $crate::element::ElementData::$element_type(ref e) => &*e,
277 _ => panic!("tried to borrow_element_as {}", stringify!($element_type)),
278 })
279 };
280}
281
282pub trait NodeCascade {
284 fn cascade(&mut self, values: &ComputedValues);
285}
286
287impl NodeCascade for Node {
288 fn cascade(&mut self, values: &ComputedValues) {
289 let mut values = Box::new(values.clone());
298
299 {
300 let mut elt = self.borrow_element_mut();
301
302 elt.get_specified_values().to_computed_values(&mut values);
303 elt.set_computed_values(&values);
304 }
305
306 for mut child in self.children().filter(|c| c.is_element()) {
307 child.cascade(&values);
308 }
309 }
310}
311
312pub trait NodeDraw {
316 fn draw(
317 &self,
318 acquired_nodes: &mut AcquiredNodes<'_>,
319 cascaded: &CascadedValues<'_>,
320 viewport: &Viewport,
321 draw_ctx: &mut DrawingCtx,
322 clipping: bool,
323 ) -> DrawResult;
324
325 fn draw_children(
326 &self,
327 acquired_nodes: &mut AcquiredNodes<'_>,
328 cascaded: &CascadedValues<'_>,
329 viewport: &Viewport,
330 draw_ctx: &mut DrawingCtx,
331 clipping: bool,
332 ) -> DrawResult;
333}
334
335impl NodeDraw for Node {
336 fn draw(
337 &self,
338 acquired_nodes: &mut AcquiredNodes<'_>,
339 cascaded: &CascadedValues<'_>,
340 viewport: &Viewport,
341 draw_ctx: &mut DrawingCtx,
342 clipping: bool,
343 ) -> DrawResult {
344 match *self.borrow() {
345 NodeData::Element(ref e) => {
346 rsvg_log!(draw_ctx.session(), "({}", e);
347 draw_ctx.print_stack_depth("Node::draw");
348 let res = match e.draw(self, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
349 {
350 Ok(bbox) => Ok(bbox),
351
352 Err(boxed_e) => match *boxed_e {
353 InternalRenderingError::InvalidTransform => Ok(viewport.empty_bbox()),
359
360 InternalRenderingError::CircularReference(node) => {
361 if node != *self {
362 return Ok(viewport.empty_bbox());
363 } else {
364 return Err(Box::new(InternalRenderingError::CircularReference(
365 node,
366 )));
367 }
368 }
369
370 _ => Err(boxed_e),
371 },
372 };
373
374 rsvg_log!(draw_ctx.session(), ")");
375
376 res
377 }
378
379 _ => Ok(viewport.empty_bbox()),
380 }
381 }
382
383 fn draw_children(
384 &self,
385 acquired_nodes: &mut AcquiredNodes<'_>,
386 cascaded: &CascadedValues<'_>,
387 viewport: &Viewport,
388 draw_ctx: &mut DrawingCtx,
389 clipping: bool,
390 ) -> DrawResult {
391 draw_ctx.print_stack_depth("Node::draw_children");
392
393 let mut bbox = viewport.empty_bbox();
394
395 for child in self.children().filter(|c| c.is_element()) {
396 let child_bbox = draw_ctx.draw_node_from_stack(
397 &child,
398 acquired_nodes,
399 &CascadedValues::clone_with_node(cascaded, &child),
400 viewport,
401 clipping,
402 )?;
403 bbox.insert(&child_bbox);
404 }
405
406 Ok(bbox)
407 }
408}