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}
185
186pub trait NodeBorrow {
188 fn is_element(&self) -> bool;
190
191 fn is_chars(&self) -> bool;
193
194 fn borrow_chars(&self) -> Ref<'_, Chars>;
198
199 fn borrow_element(&self) -> Ref<'_, Element>;
203
204 fn borrow_element_mut(&mut self) -> RefMut<'_, Element>;
208
209 fn borrow_element_data(&self) -> Ref<'_, ElementData>;
213}
214
215impl NodeBorrow for Node {
216 fn is_element(&self) -> bool {
217 matches!(*self.borrow(), NodeData::Element(_))
218 }
219
220 fn is_chars(&self) -> bool {
221 matches!(*self.borrow(), NodeData::Text(_))
222 }
223
224 fn borrow_chars(&self) -> Ref<'_, Chars> {
225 Ref::map(self.borrow(), |n| match n {
226 NodeData::Text(c) => &**c,
227 _ => panic!("tried to borrow_chars for a non-text node"),
228 })
229 }
230
231 fn borrow_element(&self) -> Ref<'_, Element> {
232 Ref::map(self.borrow(), |n| match n {
233 NodeData::Element(e) => &**e,
234 _ => panic!("tried to borrow_element for a non-element node"),
235 })
236 }
237
238 fn borrow_element_mut(&mut self) -> RefMut<'_, Element> {
239 RefMut::map(self.borrow_mut(), |n| match &mut *n {
240 NodeData::Element(e) => &mut **e,
241 _ => panic!("tried to borrow_element_mut for a non-element node"),
242 })
243 }
244
245 fn borrow_element_data(&self) -> Ref<'_, ElementData> {
246 Ref::map(self.borrow(), |n| match n {
247 NodeData::Element(e) => &e.element_data,
248 _ => panic!("tried to borrow_element_data for a non-element node"),
249 })
250 }
251}
252
253#[doc(hidden)]
254#[macro_export]
255macro_rules! is_element_of_type {
256 ($node:expr, $element_type:ident) => {
257 matches!(
258 $node.borrow_element().element_data,
259 $crate::element::ElementData::$element_type(_)
260 )
261 };
262}
263
264#[doc(hidden)]
265#[macro_export]
266macro_rules! borrow_element_as {
267 ($node:expr, $element_type:ident) => {
268 std::cell::Ref::map($node.borrow_element_data(), |d| match d {
269 &$crate::element::ElementData::$element_type(ref e) => &*e,
270 _ => panic!("tried to borrow_element_as {}", stringify!($element_type)),
271 })
272 };
273}
274
275pub trait NodeCascade {
277 fn cascade(&mut self, values: &ComputedValues);
278}
279
280impl NodeCascade for Node {
281 fn cascade(&mut self, values: &ComputedValues) {
282 let mut values = Box::new(values.clone());
291
292 {
293 let mut elt = self.borrow_element_mut();
294
295 elt.get_specified_values().to_computed_values(&mut values);
296 elt.set_computed_values(&values);
297 }
298
299 for mut child in self.children().filter(|c| c.is_element()) {
300 child.cascade(&values);
301 }
302 }
303}
304
305pub 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 ) -> DrawResult;
317
318 fn draw_children(
319 &self,
320 acquired_nodes: &mut AcquiredNodes<'_>,
321 cascaded: &CascadedValues<'_>,
322 viewport: &Viewport,
323 draw_ctx: &mut DrawingCtx,
324 ) -> DrawResult;
325}
326
327impl NodeDraw for Node {
328 fn draw(
329 &self,
330 acquired_nodes: &mut AcquiredNodes<'_>,
331 cascaded: &CascadedValues<'_>,
332 viewport: &Viewport,
333 draw_ctx: &mut DrawingCtx,
334 clipping: bool,
335 ) -> DrawResult {
336 match *self.borrow() {
337 NodeData::Element(ref e) => {
338 rsvg_log!(draw_ctx.session(), "({}", e);
339 draw_ctx.print_stack_depth("Node::draw");
340 let res = match e.draw(self, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
341 {
342 Ok(bbox) => Ok(bbox),
343
344 Err(boxed_e) => match *boxed_e {
345 InternalRenderingError::InvalidTransform => Ok(viewport.empty_bbox()),
351
352 InternalRenderingError::CircularReference(node) => {
353 if node != *self {
354 return Ok(viewport.empty_bbox());
355 } else {
356 return Err(Box::new(InternalRenderingError::CircularReference(
357 node,
358 )));
359 }
360 }
361
362 _ => Err(boxed_e),
363 },
364 };
365
366 rsvg_log!(draw_ctx.session(), ")");
367
368 res
369 }
370
371 _ => Ok(viewport.empty_bbox()),
372 }
373 }
374
375 fn draw_children(
376 &self,
377 acquired_nodes: &mut AcquiredNodes<'_>,
378 cascaded: &CascadedValues<'_>,
379 viewport: &Viewport,
380 draw_ctx: &mut DrawingCtx,
381 ) -> DrawResult {
382 draw_ctx.print_stack_depth("Node::draw_children");
383
384 let mut bbox = viewport.empty_bbox();
385
386 for child in self.children().filter(|c| c.is_element()) {
387 let child_bbox = draw_ctx.draw_node_from_stack(
388 &child,
389 acquired_nodes,
390 &CascadedValues::clone_with_node(cascaded, &child),
391 viewport,
392 )?;
393 bbox.insert(&child_bbox);
394 }
395
396 Ok(bbox)
397 }
398}