Re: Confused about GDKPixBuf/Cairo interaction



Le 18/02/2013 14:50, Rena a écrit :
On Mon, Feb 18, 2013 at 8:35 AM, Colomban Wendling
<lists ban herbesfolles org> wrote:
Hi,

Le 18/02/2013 11:10, Rena a écrit :
Hi, just joined the mailing list, been using GTK and related projects
for a while now. Recently I've been developing a Game Boy emulator
that uses GtkDrawingArea and GdkPixbuf to display the game screen.

In addition to the game output I want to also be able to draw text and
shapes on the display window, and Cairo seems to be the ideal way to
draw shapes. I'm already using Cairo to copy the Pixbuf to the
GtkDrawingArea, so that seems like a good sign that Cairo and
GdkPixbuf should interact nicely.

[...]

I don't really get it.  You say you already use Cairo to draw your
pixbuf, but also that you can't see how to use a GdkPixbuf with Cairo?
This seems contradictory to me.

Anyway, what you want is gdk_cairo_set_source_pixbuf()[1] that does the
appropriate conversions to create a Cairo pattern from a GdkPixbuf.
Then you can use this pattern like any other Cairo pattern (e.g.
cairo_paint()), and you're done.

Well, in the GtkDrawingArea::draw signal, I receive a cairo_t* that
Gdk has created for me, and draw my pixbuf to it:

gboolean draw_callback(GtkWidget *widget, cairo_t *cairo) {
    gdk_cairo_set_source_pixbuf(cairo, pixbuf, 0, 0);
    cairo_paint(cairo);
}

but if I want to draw a shape on the pixbuf, I would need to create a
cairo_t* of my own for that purpose, and I don't see how to create one
that's compatible with the pixel format GdkPixbuf uses. i.e. I want
the destination to be my pixbuf, not the source.

First, you could very well draw directly on the Cairo context straight
in the ::draw handler, give then you don't need caching for decent
performances.  E.g., just continue drawing stuff in the ::draw handler
after you painted the pixbuf.

But if you want to draw everything on your own surface and then paint
that surface in the ::draw handler, just create a surface with whatever
format you need, gdk_cairo_set_source_pixbuf() should be able to do the
conversion.

The other solution is to use cairo_surface_create_similar(), but this
requires a surface to be similar to -- but there is no much reason for
that other surface to have a format better suitable to your pixbuf.  The
Cairo context passed to the ::draw handler is appropriate to draw on the
screen, not particularly to draw your pixbuf.


But you can very well do this:

def prepare_suraface(pix):
  # use whatever format you need, e.g. ARGB32 or RGB24
  surface = Cairo.Surface(cairo.Format.ARGB32, pix.width, pix.height)
  cr = Cairo.Context(surface)
  Gdk.cairo_set_source_pixbuf(cr, pix, 0, 0)
  cr.pain()

  # and continue drawing stuff
  cr.move_to(0, 0)
  cr.line_to(pix.width, pix.height)
  cr.stroke()

  return surface

and then your simply paint the created surface in your ::draw handler.
Of course, doing this is only useful if you need caching the drawn
surface, otherwise it'd be faster do directly perform the draws on the
::draw handler.


Or maybe I got you wrong and you'd like to *draw* on your GdkPixbuf?
I'm afraid this just isn't possible directly.  If you really want to do
that, you'll probably have to manually do some pixel conversion.  You
can create a Cairo surface of the pixbuf's size, draw on that, and then
get the surface's pixels which you'd convert manually to the pixbuf
format, and push those pixels to the pixbuf.  But again, why would you
need to draw specifically on a GdkPixbuf?

Regards,
Colomban


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]