[librsvg: 7/13] New StackingContext struct




commit ad7b9bfefe84c0d231255473b69f9ba7474f083c
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue May 11 12:53:32 2021 -0500

    New StackingContext struct
    
    Let's create a layout tree from the DOM tree!
    
    This commit introduces StackingContext, or "all the shit that
    DrawingCtx::with_discrete_layer() pulls out of the node being rendered
    and the ComputedValues".  That information is what the SVG spec says
    would be necessary to determine whether an element establishes a
    stacking context, to be rendered as an isolated group or not -
    basically librsvg's needs_temporary_surface flag.
    
    For now, StackingContext just holds the transform.  I'll be moving the
    other parameters into it in separate commits.

 Makefile.am        |  1 +
 src/drawing_ctx.rs | 30 ++++++++++++++++++++++--------
 src/layout.rs      | 30 ++++++++++++++++++++++++++++++
 src/lib.rs         |  1 +
 src/marker.rs      |  5 ++++-
 src/structure.rs   | 17 +++++++++++++----
 src/text.rs        |  5 ++++-
 7 files changed, 75 insertions(+), 14 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 439ced85..c404ca86 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -77,6 +77,7 @@ LIBRSVG_SRC =                                 \
        src/image.rs                            \
        src/io.rs                               \
        src/iri.rs                              \
+       src/layout.rs                           \
        src/length.rs                           \
        src/lib.rs                              \
        src/limits.rs                           \
diff --git a/src/drawing_ctx.rs b/src/drawing_ctx.rs
index ba80684e..a01180e5 100644
--- a/src/drawing_ctx.rs
+++ b/src/drawing_ctx.rs
@@ -20,6 +20,7 @@ use crate::error::{AcquireError, ImplementationLimit, RenderingError};
 use crate::filters::{self, FilterSpec};
 use crate::float_eq_cairo::ApproxEqCairo;
 use crate::gradient::{GradientVariant, SpreadMethod, UserSpaceGradient};
+use crate::layout::StackingContext;
 use crate::length::*;
 use crate::marker;
 use crate::node::{CascadedValues, Node, NodeBorrow, NodeDraw};
@@ -572,13 +573,15 @@ impl DrawingCtx {
 
             let mut mask_draw_ctx = self.nested(mask_cr);
 
+            let stacking_ctx = StackingContext::new(Transform::identity());
+
             let res = mask_draw_ctx.with_discrete_layer(
+                &stacking_ctx,
                 mask_node,
                 acquired_nodes,
                 values,
                 false,
                 None,
-                Transform::identity(),
                 &mut |an, dc| mask_node.draw_children(an, &cascaded, dc, false),
             );
 
@@ -596,12 +599,12 @@ impl DrawingCtx {
 
     pub fn with_discrete_layer(
         &mut self,
+        stacking_ctx: &StackingContext,
         node: &Node,
         acquired_nodes: &mut AcquiredNodes<'_>,
         values: &ComputedValues,
         clipping: bool,
         clip_rect: Option<Rect>,
-        transform: Transform,
         draw_fn: &mut dyn FnMut(
             &mut AcquiredNodes<'_>,
             &mut DrawingCtx,
@@ -609,7 +612,7 @@ impl DrawingCtx {
     ) -> Result<BoundingBox, RenderingError> {
         let orig_transform = self.get_transform();
 
-        self.cr.transform(transform.into());
+        self.cr.transform(stacking_ctx.transform.into());
 
         let res = if clipping {
             draw_fn(acquired_nodes, self)
@@ -1008,13 +1011,16 @@ impl DrawingCtx {
                     let pattern_cascaded =
                         CascadedValues::new_from_node(&pattern.node_with_children);
                     let pattern_values = pattern_cascaded.get();
+
+                    let stacking_ctx = StackingContext::new(Transform::identity());
+
                     dc.with_discrete_layer(
+                        &stacking_ctx,
                         &pattern.node_with_children,
                         acquired_nodes,
                         pattern_values,
                         false,
                         None,
-                        Transform::identity(),
                         &mut |an, dc| {
                             pattern.node_with_children.draw_children(
                                 an,
@@ -1188,13 +1194,15 @@ impl DrawingCtx {
             return Ok(self.empty_bbox());
         }
 
+        let stacking_ctx = StackingContext::new(node.borrow_element().get_transform());
+
         self.with_discrete_layer(
+            &stacking_ctx,
             node,
             acquired_nodes,
             values,
             clipping,
             None,
-            node.borrow_element().get_transform(),
             &mut |an, dc| {
                 let cr = dc.cr.clone();
                 let transform = dc.get_transform();
@@ -1297,13 +1305,15 @@ impl DrawingCtx {
             None
         };
 
+        let stacking_ctx = StackingContext::new(node.borrow_element().get_transform());
+
         self.with_discrete_layer(
+            &stacking_ctx,
             node,
             acquired_nodes,
             values,
             clipping,
             None,
-            node.borrow_element().get_transform(),
             &mut |_an, dc| {
                 let saved_cr = SavedCr::new(dc);
 
@@ -1608,13 +1618,15 @@ impl DrawingCtx {
                 None
             };
 
+            let stacking_ctx = StackingContext::new(Transform::identity());
+
             self.with_discrete_layer(
+                &stacking_ctx,
                 node,
                 acquired_nodes,
                 values,
                 clipping,
                 None,
-                Transform::identity(),
                 &mut |an, dc| {
                     let _params = dc.push_new_viewport(
                         symbol.get_viewbox(),
@@ -1634,13 +1646,15 @@ impl DrawingCtx {
         } else {
             // otherwise the referenced node is not a <symbol>; process it generically
 
+            let stacking_ctx = StackingContext::new(Transform::new_translate(use_rect.x0, use_rect.y0));
+
             self.with_discrete_layer(
+                &stacking_ctx,
                 node,
                 acquired_nodes,
                 values,
                 clipping,
                 None,
-                Transform::new_translate(use_rect.x0, use_rect.y0),
                 &mut |an, dc| {
                     child.draw(
                         an,
diff --git a/src/layout.rs b/src/layout.rs
new file mode 100644
index 00000000..a29b35af
--- /dev/null
+++ b/src/layout.rs
@@ -0,0 +1,30 @@
+//! Layout tree.
+//!
+//! The idea is to take the DOM tree and produce a layout tree with SVG concepts.
+
+use crate::transform::Transform;
+
+/// SVG Stacking context, an inner node in the layout tree.
+///
+/// https://www.w3.org/TR/SVG2/render.html#EstablishingStackingContex
+///
+/// This is not strictly speaking an SVG2 stacking context, but a
+/// looser version of it.  For example. the SVG spec mentions that a
+/// an element should establish a stacking context if the `filter`
+/// property applies to the element and is not `none`.  In that case,
+/// the element is rendered as an "isolated group" -
+/// https://www.w3.org/TR/2015/CR-compositing-1-20150113/#csscompositingrules_SVG
+///
+/// Here we store all the parameters that may lead to the decision to actually
+/// render an element as an isolated group.
+pub struct StackingContext {
+    pub transform: Transform,
+}
+
+impl StackingContext {
+    pub fn new(transform: Transform) -> StackingContext {
+        StackingContext {
+            transform,
+        }
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 694dca76..1c6f5633 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -204,6 +204,7 @@ mod href;
 mod image;
 mod io;
 mod iri;
+mod layout;
 mod length;
 mod limits;
 mod marker;
diff --git a/src/marker.rs b/src/marker.rs
index 068800b4..b0c05137 100644
--- a/src/marker.rs
+++ b/src/marker.rs
@@ -15,6 +15,7 @@ use crate::element::{Draw, Element, ElementResult, SetAttributes};
 use crate::error::*;
 use crate::float_eq_cairo::ApproxEqCairo;
 use crate::iri::Iri;
+use crate::layout::StackingContext;
 use crate::length::*;
 use crate::node::{CascadedValues, Node, NodeBorrow, NodeDraw};
 use crate::parsers::{Parse, ParseValue};
@@ -159,13 +160,15 @@ impl Marker {
             )
         };
 
+        let stacking_ctx = StackingContext::new(transform);
+
         draw_ctx.with_discrete_layer(
+            &stacking_ctx,
             node,
             acquired_nodes,
             values,
             clipping,
             clip,
-            transform,
             &mut |an, dc| node.draw_children(an, &cascaded, dc, clipping),
         )
     }
diff --git a/src/structure.rs b/src/structure.rs
index 82d7ff98..e872fd49 100644
--- a/src/structure.rs
+++ b/src/structure.rs
@@ -10,6 +10,7 @@ use crate::drawing_ctx::{ClipMode, DrawingCtx, ViewParams};
 use crate::element::{Draw, ElementResult, SetAttributes};
 use crate::error::*;
 use crate::href::{is_href, set_href};
+use crate::layout::StackingContext;
 use crate::length::*;
 use crate::node::{CascadedValues, Node, NodeBorrow, NodeDraw};
 use crate::parsers::{Parse, ParseValue};
@@ -33,13 +34,15 @@ impl Draw for Group {
     ) -> Result<BoundingBox, RenderingError> {
         let values = cascaded.get();
 
+        let stacking_ctx = StackingContext::new(node.borrow_element().get_transform());
+
         draw_ctx.with_discrete_layer(
+            &stacking_ctx,
             node,
             acquired_nodes,
             values,
             clipping,
             None,
-            node.borrow_element().get_transform(),
             &mut |an, dc| node.draw_children(an, cascaded, dc, clipping),
         )
     }
@@ -72,13 +75,15 @@ impl Draw for Switch {
     ) -> Result<BoundingBox, RenderingError> {
         let values = cascaded.get();
 
+        let stacking_ctx = StackingContext::new(node.borrow_element().get_transform());
+
         draw_ctx.with_discrete_layer(
+            &stacking_ctx,
             node,
             acquired_nodes,
             values,
             clipping,
             None,
-            node.borrow_element().get_transform(),
             &mut |an, dc| {
                 if let Some(child) = node.children().filter(|c| c.is_element()).find(|c| {
                     let elt = c.borrow_element();
@@ -247,13 +252,15 @@ impl Draw for Svg {
     ) -> Result<BoundingBox, RenderingError> {
         let values = cascaded.get();
 
+        let stacking_ctx = StackingContext::new(node.borrow_element().get_transform());
+
         draw_ctx.with_discrete_layer(
+            &stacking_ctx,
             node,
             acquired_nodes,
             values,
             clipping,
             None,
-            node.borrow_element().get_transform(),
             &mut |an, dc| {
                 let _params = self.push_viewport(node, cascaded, dc);
                 node.draw_children(an, cascaded, dc, clipping)
@@ -496,13 +503,15 @@ impl Draw for Link {
         let cascaded = CascadedValues::new(cascaded, node);
         let values = cascaded.get();
 
+        let stacking_ctx = StackingContext::new(node.borrow_element().get_transform());
+
         draw_ctx.with_discrete_layer(
+            &stacking_ctx,
             node,
             acquired_nodes,
             values,
             clipping,
             None,
-            node.borrow_element().get_transform(),
             &mut |an, dc| match self.link.as_ref() {
                 Some(l) if !l.is_empty() => {
                     dc.with_link_tag(l, &mut |dc| node.draw_children(an, &cascaded, dc, clipping))
diff --git a/src/text.rs b/src/text.rs
index fa3d0891..be978491 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -10,6 +10,7 @@ use crate::drawing_ctx::DrawingCtx;
 use crate::element::{Draw, Element, ElementResult, SetAttributes};
 use crate::error::*;
 use crate::font_props::FontWeight;
+use crate::layout::StackingContext;
 use crate::length::*;
 use crate::node::{CascadedValues, Node, NodeBorrow};
 use crate::parsers::ParseValue;
@@ -491,13 +492,15 @@ impl Draw for Text {
         let view_params = draw_ctx.get_view_params();
         let params = NormalizeParams::new(&values, &view_params);
 
+        let stacking_ctx = StackingContext::new(node.borrow_element().get_transform());
+
         draw_ctx.with_discrete_layer(
+            &stacking_ctx,
             node,
             acquired_nodes,
             values,
             clipping,
             None,
-            node.borrow_element().get_transform(),
             &mut |an, dc| {
                 let mut x = self.x.to_user(&params);
                 let mut y = self.y.to_user(&params);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]