[cairo] Vector screen capture with Cairo

Carl Worth cworth at cworth.org
Wed Apr 4 14:07:12 PDT 2007


On Wed, 04 Apr 2007 21:23:26 +0100, Peter Clifton wrote:
> > I want to get a vector-based a window capture of a program for
> inclusion
> > in user-documentation. This would produce a nice scalable, (and
> > hopefully memory efficient) way to embed the window capture.

Hi Peter,

I think this is a really interesting thing that you are looking into,
and I'm looking forward to hearing more from you as you make progress.

> Each X11 drawable the app wants to paint has a cairo surface created for
> it, and subsequently a graphics context.

I'm curious how many of these you are seeing. My understanding is that historically
GTK+ used a separate X11 Window for every widget, and so each
application window would have a fairly deep corresponding hierarchy of
X11 Windows. But I also understand that in recent versions of GTK+
that it uses X in a much more flat style, with several layers of GTK+
widget hierarchy drawing to the same X11 Window.

> Can I have multiple cairo contexts painting to different areas of
> my .pdf surface concurrently?

What do you mean by "concurrently" exactly? You can definitely create
multiple cairo contexts that all target the same surface. And for each
context, you can setup a different translation matrix and even a
different clip so that each is painting to a different area.

As for concurrence, cairo would not be happy if you were modifying the
contents of the same surface, (or any other user-created cairo object
for that matter), from multiple threads concurrently. But otherwise,
you should be fine.

> Can I make a surface backed pattern which can be "painted" onto the .pdf
> - or will this rasterize the graphics?

Yes, you can create a pattern from one PDF surface,
(cairo_pattern_create_for_surface, or even implicitly with just
cairo_set_source_surface). And you can then paint with this pattern to
another PDF surface.

*BUT*, as you anticipated, this will currently trigger rasterization
of the source pattern.

This is certainly something that could be fixed in cairo, and it would
be extremely useful, (and Kristian I think even had some functional
support for this kind of thing in an early version of cairo's PDF
surface).

If you want to look into the issue, the function of interest is:

	_cairo_pdf_surface_emit_surface_pattern

Notice the comment that reads:

	/* XXX: Should do something clever here for PDF source surfaces ? */

and notice that the next operation is to call
_cairo_surface_acquire_source_image on the source pattern's surface,
(which explicitly asks for a rasterized version of the source
surface). So, instead, emitting a vector version of the source
surface, (which should be straightforward as cairo already does know
how to emit vector PDF after all), is what should happen there---to
form a native PDF pattern rather than an image pattern in the
resulting PDF.

Also, one thing you should be aware of if you're going to get into
this, is that what I've been calling a "PDF source surface" won't
actually be a PDF surface inside of cairo, but will be a "meta
surface" that can be replayed as native PDF, (this is exactly what's
already happening under the hood for all PDF surfaces anyway).

Oh, and to create the little intermediate, sub-surfaces that you want,
the best thing is to just call cairo_surface_create_similar for each,
passing the final PDF surface as the template, (since you don't want
to actually create intermediate PDF surfaces, since that requires a
destination file name).

And here, there's another current limitation which is that there
currently isn't a _cairo_pdf_create_similar function. This means that
your "similar" surface will be an image surface from the beginning
instead of a meta-surface like you want to get into the code paths I
described above.

I know that Adrian Johnson has already started looking into making
create_similar return a meta-surface for the PDF backend, (note that
cairo already returns a meta-surface for the SVG backend, for
example). And he may also be planning on doing all the work that I'm
suggesting above, (quite likely in fact, as getting a meta-surface fro
create_similar isn't really useful without it).

So I'll let him comment on his progress as far as that goes.

> I'm realising this is far from "easy", but it still looks possible. Any
> further comments?

Don't forget that if it were all easy, it wouldn't be nearly so much
fun!

Also, as has been mentioned earlier in the thread, GTK+ doesn't
currently draw everything with cairo---many GDK functions still bypass
cairo. So you'll probably need to address that as well to get your
code to work reliably.

And finally, you talked about starting up the program to be
screenshotted and informing it to arrange itself as desired. A much
more interesting approach would involve putting an unmodified
application into the desired state through whatever means, then
signalling it in some fashion, and having GTK+ respond to the signal
by setting up the PDF-targeting cairo context[*] and forcing a full
expose to the application.

-Carl

[*] One annoyance here is that GTK+ doesn't actually create and pass a
context to the application, but expects the application to create the
cairo context when it's exposed. But it does do that with
gdk_cairo_create, so you do at least have a place to hook in and
ensure the application gets a context targeting the cairo surface that
you really want. But, presumably you've already figured this much out
anyway.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20070404/ca84282e/attachment.pgp


More information about the cairo mailing list