haskellgtkcairohaskell-diagrams

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

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