Viewport abstraction 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), the preserveAspectRatio and viewBox 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, 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 from into

  • Add the necessary fields from the previous section (element’s transform, perhaps moved from the StackingCtx), the viewport size, preserveAspectRatio, and overflow.

  • (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.