[cairo] How do you get tight bounding boxes and/or unused margins cropped for final libcairo results?
Behdad Esfahbod
behdad at behdad.org
Mon Sep 10 14:01:24 PDT 2007
On Mon, 2007-09-10 at 13:40 -0700, Alan W. Irwin wrote:
> 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?
Yes, that's the idea.
> > 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.
What most people do is not saving and replaying, but to just play twice.
That is, they have a function that draws to a cairo_surface_t and
calculates the extents at the same time too. They can then do:
surface = cairo_pdf_surface_create (filename, 1, 1);
draw (surface, &width, &height);
cairo_surface_destroy (surface);
surface = cairo_pdf_surface_create (filename, width, height);
draw (surface, NULL, NULL);
cairo_surface_destroy (surface);
Something like that.
behdad
> Alan
> __________________________
> 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
> (lbproject.sf.net).
> __________________________
>
> Linux-powered Science
> __________________________
--
behdad
http://behdad.org/
"Those who would give up Essential Liberty to purchase a little
Temporary Safety, deserve neither Liberty nor Safety."
-- Benjamin Franklin, 1759
More information about the cairo
mailing list