summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@gnome.org>2023-03-22 19:10:16 -0600
committerMarge Bot <marge-bot@gnome.org>2023-03-23 01:41:14 +0000
commit45f8c8dbe21259325c7ef511adaf440c7eb8701f (patch)
treea89a388cca69e90e17487764024456b8d36f8b0b
parenta63cc38ae8a62eaebf074eb8dca391c1d823370a (diff)
downloadlibrsvg-45f8c8dbe21259325c7ef511adaf440c7eb8701f.tar.gz
roadmap: better explain the purpose of the render tree, hopefully
Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/816>
-rw-r--r--devel-docs/render_tree.rst51
-rw-r--r--devel-docs/roadmap.rst2
2 files changed, 52 insertions, 1 deletions
diff --git a/devel-docs/render_tree.rst b/devel-docs/render_tree.rst
index 01e40e44..1dee8710 100644
--- a/devel-docs/render_tree.rst
+++ b/devel-docs/render_tree.rst
@@ -1,6 +1,57 @@
Render tree
===========
+For historical reasons, librsvg's code flow during rendering is as
+follows. The rendering code traverses the SVG tree of elements, and
+for each one, its ``::draw()`` method is called; its signature looks
+like this (some arguments omitted):
+
+.. code-block:: rust
+
+ pub fn draw(
+ &self,
+ ...
+ draw_ctx: &mut DrawingCtx,
+ ) -> Result<BoundingBox, RenderingError> { ... }
+
+The draw() methods perform the actual rendering as side effects on the
+``draw_ctx``, and return a ``BoundingBox``. That is, the bounding box of
+an element is computed at the same time that it is rendered. This is
+suboptimal for several reasons:
+
+- Many things that happen during rendering depend on knowing the
+ bounding box. For example, gradients, patterns, and filters with
+ units set to ``objectBoundingBox`` need to know the bounds. The
+ rendering code in drawing_ctx.rs is cluttered because it must
+ resolve bounding boxes very late.
+
+- This is especially problematic for filters, since a Cairo surface
+ needs to be created *before* rendering, and that surface should have
+ a size relative to the bounding box of the element being filtered!
+ `Bug #1 <https://gitlab.gnome.org/GNOME/librsvg/-/issues/1>`_ is
+ precisely about this: librsvg instead creates a temporary surface as
+ big as the document's toplevel viewport and filters it, but this
+ doesn't work well for filters like Gaussian blur that should
+ actually reference pixels outside of the document's area (think of a
+ shape that extends past the document's area, which then gets
+ blurred).
+
+- The way for an element to signal that it is not drawable
+ (e.g. ``<defs>`` is by returning an empty bounding box and not
+ rendering anything. This is awkward.
+
+- When rendering to a temporary surface for filtering or masking,
+ there is a set of affine transformations that needs to be maintained
+ carefully: an affine for the clipping path outside the temporary
+ surface, an affine for drawing inside the surface, an affine to
+ composite the surface into the final result. This is hard to
+ understand and hard to test.
+
+These problems can be solved by having a **render tree**.
+
+What is a render tree?
+----------------------
+
As of 2022/Oct/06, librsvg does not compute a render tree data
structure prior to rendering. Instead, in a very 2000s fashion, it
walks the tree of elements and calls a ``.draw()`` method for each
diff --git a/devel-docs/roadmap.rst b/devel-docs/roadmap.rst
index 6e3f8007..bbbd22e4 100644
--- a/devel-docs/roadmap.rst
+++ b/devel-docs/roadmap.rst
@@ -17,7 +17,7 @@ Short term
offsetting for layers with opacity. Solving this should make it easier to fix the root
cause of `issue #1 <https://gitlab.gnome.org/GNOME/librsvg/-/issues/1>`_, where librsvg
cannot compute arbitrary regions for filter effects and it only takes the user-specified
- viewport into account.
+ viewport into account. See :doc:`render_tree` for details on this.
- Continue with the revamp of :doc:`text_layout`.