[librsvg: 7/13] New StackingContext struct
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 7/13] New StackingContext struct
- Date: Wed, 12 May 2021 01:04:22 +0000 (UTC)
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(¶ms);
let mut y = self.y.to_user(¶ms);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]