Extract bounding box computation from the drawing process
The drawing process conflates the actual drawing, and computing the bounding boxes of elements. This is clearly seen in NodeTrait::draw() -> Result<BoundingBox, ...>
. An Ok()
there means that the element was drawn to the DrawingCtx and the bounding box was computed and returned.
Since there is no distinction between drawing and computing bboxes, this means that the public API's "give me the geometry of an element" involves actually drawing stuff to an image surface that is thrown away. We use an 1x1-pixel surface and hope that Cairo will be smart enough to cull everything, but who knows.
Also, computing geometries basically just needs the paths and their stroke widths; it doesn't need to generate patterns, render gradients, etc. Basically just what we have in compute_stroke_and_fill_box()
, plus the special case for text-with-stroke in PositionedSpan::draw()
.
I think we can have two separate methods:
-
compute_bbox() -> BoundingBox
- just does that without drawing. -
draw()
- as usual.
To avoid converting everything in a single step, I want to experiment with the following steps:
- Add
NodeTrait::can_compute_bbox() -> bool
, returns false by default. - Add
NodeTrait::compute_bbox() -> BoundingBox
, returns an empty bbox by default. - Convert all of shapes.rs to compute the bboxes separately from drawing; make their
::draw()
still return the bbox as usual... - ... until we figure out how the nodes in structure.rs need to change to aggregate the bboxes of their children. This may need some duplication of the logic from the draw method, hopefully to be refactored away.
After this is done, I think we can move on to producing a render tree instead of doing everything during drawing. This may make it easier to support other backends than Cairo.
I'll start a branch for this.