diff options
author | Federico Mena Quintero <federico@gnome.org> | 2023-03-22 19:10:16 -0600 |
---|---|---|
committer | Marge Bot <marge-bot@gnome.org> | 2023-03-23 01:41:14 +0000 |
commit | 45f8c8dbe21259325c7ef511adaf440c7eb8701f (patch) | |
tree | a89a388cca69e90e17487764024456b8d36f8b0b | |
parent | a63cc38ae8a62eaebf074eb8dca391c1d823370a (diff) | |
download | librsvg-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.rst | 51 | ||||
-rw-r--r-- | devel-docs/roadmap.rst | 2 |
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`. |