[librsvg] ARCHITECTURE.md: Start describing our single-pass CSS cascade / rendering process
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] ARCHITECTURE.md: Start describing our single-pass CSS cascade / rendering process
- Date: Tue, 20 Mar 2018 23:20:56 +0000 (UTC)
commit bfbc52f658a107eb83dbc764c45507deee627f91
Author: Federico Mena Quintero <federico gnome org>
Date: Tue Mar 20 17:11:08 2018 -0600
ARCHITECTURE.md: Start describing our single-pass CSS cascade / rendering process
ARCHITECTURE.md | 46 +++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 43 insertions(+), 3 deletions(-)
---
diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md
index 1f394668..3c464507 100644
--- a/ARCHITECTURE.md
+++ b/ARCHITECTURE.md
@@ -42,7 +42,7 @@ During its lifetime, an `RsvgHandle` can be in either of two stages:
* Rendering - the SVG is finished loading. The caller can then render
the image as many times as it wants to Cairo contexts.
-
+
## Loading SVG data
The following happens in `rsvg_handle_read_stream_sync()`:
@@ -50,7 +50,7 @@ The following happens in `rsvg_handle_read_stream_sync()`:
* The function peeks the first bytes of the stream to see if it is
compressed with gzip. In that case, it plugs a
`g_zlib_decompressor_new()` to the use-supplied stream.
-
+
* The function creates an XML parser for the stream. The SAX parser's
callbacks are functions that create DOM-like objects within the
`RsvgHandle`. The most important callback is
@@ -101,7 +101,7 @@ computed or actually used values will be generated at rendering time.
# Rendering
-The public `rsvg_handle_render_cairo()` and `rsvg_handle_cairo_sub()`
+The public `rsvg_handle_render_cairo()` and `rsvg_handle_render_cairo_sub()`
functions initiate a rendering process; the first function just calls
the second one with the root element of the SVG.
@@ -112,6 +112,46 @@ rendering functions. It carries the vtable for rendering in the
`state` field, and other values which are changed as rendering
progresses.
+## CSS cascading
+
+For historical reasons, librsvg does the CSS cascade *and* rendering
+in a single traversal of the tree of nodes. This is somewhat awkward,
+and in the future we hope to move to a Servo-like model where CSS is
+cascaded and sizes are resolved before rendering.
+
+Rendering starts at `rsvg_handle_render_cairo_sub()`. It calls
+`rsvg_cairo_new_drawing_ctx()`, which creates an `RsvgDrawingCtx` with
+a default `state`: this is the default CSS state per
+`rsvg_state_init()` (in reality that state carries an affine
+transformation already set up for this rendering pass; we can ignore
+it for now).
+
+Then, `rsvg_handle_render_cairo_sub()` starts the recursive drawing
+process by calling
+`rsvg_drawing_ctx_draw_node_from_stack()`, starting at the tree root
+(`handle->priv->treebase`). In turn, that function creates a
+temporary `state` struct by calling `rsvg_state_push()`, calls
+`rsvg_node_draw()` on the current node, and destroys the temporary
+`state` struct with `rsvg_state_pop()`.
+
+Each node draws itself in the following way:
+
+* It resolves relative lengths from the size of current viewport by calling
+ `length.normalize()` on each length value. The size of the current
+ viewport is maintained as a stack of `RsvgBbox` structures (it
+ stands for "bounding box").
+
+* It calls drawing_ctx::state_reinherit_top() with the node's own
+ `state` field. This causes the temporary state in the `draw_ctx` to
+ obtain the final cascaded CSS values.
+
+* It calls the low-level rendering functions like
+ `drawing_ctx::render_path_builder()` or
+ `drawing_ctx::render_pango_layout()`. These functions translate the
+ values from the `state` in the `draw_ctx` into Cairo values, they
+ configure the `cairo::Context`, and call actual Cairo functions to
+ draw paths/text/etc.
+
# Comparing floating-point numbers
Librsvg sometimes needs to compute things like "are these points
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]