Viewport abstraction
https://gitlab.gnome.org/GNOME/librsvg/-/issues/298 is about unifying several concepts into a Viewport abstraction. This chapter attempts to explain that.
SVG has the concept of establishing a new viewport,
in particular for the elements <svg>
and <symbol>
. The
viewport is set up like this:
Apply the element’s
transform
.Compute a transform / coordinate system from the element’s size+position (
x
,y
,width
,height
), thepreserveAspectRatio
andviewBox
attributes.Set up a clipping rectangle if the element’s
overflow
property says so.
However, that mechanism is general enough that it can also be made to
work when rendering the elements <image>
, <marker>
, and
<pattern>
. They have their own way of specifying a size (e.g. the
marker-specific markerWidth
and markerHeight
attributes), but
they also need to compute a new transform, set up clipping, etc.
The original code for librsvg reimplemented the mechanism above
independently for each of <marker>
, <symbol>
, etc., by doing
direct calls to Cairo to set up a transform and a clipping rectangle.
Unfortunately, during the initial port to Rust we did not identify
this pattern to gather the various implementations and abstract them
in a single place. Gradual refactoring led to all calls to Cairo
happening in drawing_ctx.rs
, instead of all over the code. Still,
the various versions still exist, with slightly different mechanisms
for each.
What I’d like to do
The idea in #298 is to consolidate all the parameters needed for a viewport, as mentioned above, into a single place. Now that the structs for a Render tree are starting to take hold, I think we can do these:
Move the
Viewport
struct fromdrawing_ctx.rs
intolayout.rs
.Add the necessary fields from the previous section (element’s transform, perhaps moved from the
StackingCtx
), the viewport size,preserveAspectRatio
, andoverflow
.(Look at the Firefox source code a bit before doing that; they have nice code for it.)
One by one, migrate each part of librsvg that requires it to using the new
Viewport
abstraction with everything in it. We can probably start with<svg>
and<use> / <symbol>
; markers and patterns may need a little extra untangling.