[cairo] How do you get tight bounding boxes and/or unused margins cropped for final libcairo results?

Alan W. Irwin irwin at beluga.phys.uvic.ca
Mon Sep 10 13:40:56 PDT 2007

On 2007-09-10 15:42-0400 Behdad Esfahbod wrote:

> On Mon, 2007-09-10 at 14:00 -0400, Alan W. Irwin wrote:
>> [...]Therefore, I hope there is a general
>> way to do this (crop [in the ImageMagick sense] unused margins from the
>> final result) internal to libcairo that works for some/all libcairo back ends.
>> If so, can somebody point me in the right direction?
> Hi, and welcome to cairo!
> Currently cairo surfaces need to know the size at surface creation time.
> A common approach to fixing this chicken-egg problem is that
> applications first create a 1x1 (or 0x0) dummy surface of the same type
> as the final one, render to it and compute extents (using
> cairo_stroke_extents(), cairo_fill_extents(),
> pango_layout_get_extents(), etc), and then create the final surface at
> the right size and render again.

Exactly, it is a chicken-egg problem.  :-)

I might be able to implement such a solution for our cairo devices. I guess
it would involve storing all the cairo calls in order so they can be
replayed.  That's actually not too bad since we don't use that large a
variety of libcairo calls. I presume an offset to all x and y coordinates
would also be involved for the cairo replay to fit everything inside the
smaller rectangular area.

What is the advantage to 1x1?  Does it make the first pass go a lot quicker
without affecting the calculated extents?

> I can't readily think of any generic solution to this.  For PS/PDF/SVG
> we have cairo_[ps/pdf/svg]_surface_set_size() but the docs say they
> should only be called before any drawing operations have been performed
> on the current page.  We can look into fixing this such that they work
> even after drawing to the page.  It shouldn't be *that* hard to do.  But
> this approach doesn't work for raster backends, needless to say.
> In the future we may make the cairo meta-surface public.  At that point
> you can render to the meta-surface, measure, create final surface and
> replay the meta surface to the final surface.

That would be extremely useful, but meanwhile I will probably implement the
replay scenario discussed above.  Since this appears to be a fairly common
approach to the problem, I would appreciate it if somebody could point
me to some sample code that does replays.

Alan W. Irwin

Astronomical research affiliation with Department of Physics and Astronomy,
University of Victoria (astrowww.phys.uvic.ca).

Programming affiliations with the FreeEOS equation-of-state implementation
for stellar interiors (freeeos.sf.net); PLplot scientific plotting software
package (plplot.org); the libLASi project (unifont.org/lasi); the Loads of
Linux Links project (loll.sf.net); and the Linux Brochure Project

Linux-powered Science

More information about the cairo mailing list