'How to retrieve the bounding box of an object with cairo

I'm making drawings with the Haskell cairo binding and I want to align some object vertically. To do that, I need to know the width (the bounding box or partially) of these objects.

I tried to get it by making this trick :

(origx,origy) <- getCurrentPoint -- Get the origins coordinates
setSourceRGBA 0 0 0 0            -- Make the rest of the rendering transparent
renderMyObject                   -- Rendering the object
(endx,endy) <- getCurrentPoint   -- Get the final coordinates
let width = endx - origx         -- Get the width of the object
...
translate width 0                -- Positioning according to width 
setSourceRGB 1 0 0               -- Give the final color
renderMyObject                   -- Rendering the object

The problem with this method is that it can't work if I make color change inside the rendering of the object and the calculation of the width doesn't work for all objects.

Is there a way with cairo to make "phantom" rendering on the working surface or on a dummy surface and retrieve the width and height of the object/surface ?

Note : I'm aware that the diagrams library allow to do that but for compatibility reason I can't use it for this project. But if you know how the library does, I'm interested.



Solution 1:[1]

There is no way to do that built into cairo. You have basically two options:

  1. Enforce a particular size. You can use withImageSurface to set a maximum width and height and do all your drawing on the resulting surface. Anything drawn out of bounds will simply be dropped on the floor.
  2. Compute the size. As you render, jot down the extents of each of the drawing operations you do, combining them as you go. Make your rendering operation return the combined extents to the caller.

The diagrams package opts for the latter.

Solution 2:[2]

In cairo you would use the recording surface.

  1. Create a recording surface.
  2. Render your objects to the recording surface
  3. Call cairo_recording_surface_ink_extents() to get the bounding box.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Daniel Wagner
Solution 2 user25457