Re: deprecated gtk_cairo_create
- From: rbd <rbd soest hawaii edu>
- To: gtk-app-devel-list gnome org
- Subject: Re: deprecated gtk_cairo_create
- Date: Fri, 30 Dec 2016 10:18:33 -1000 (HST)
Hello Sergei,
Unfortunately the use of the gtk3 DrawingArea is a bit obscure and
difficult to figure out. However, I have been able to make use of it very
effectively in conjunction with Cairo drawing ops.
For various reasons I have created a GUI toolkit library which lies
between my app code and gtk3. This library includes an object known as a
Canvas, which is essentially a toplevel window with scrollbars parenting a
DrawingArea. The Canvas object includes a private off-screen Cairo drawing
surface which I create and control completely, and I do all of my
application drawing onto that surface. Then, I use the gtk3 draw signal
mechanism to copy whatever recatngular areas I want from my private
surface onto the DrawingArea. gtk3 passes to my drawing event handler a
pointer to a Cairo context which addresses the DrawingArea's own Cairo
surface, so all I need to do in the draw event handler is set a source
surface on that context (in my case, the source surface is my own private
Cairo surface), and copy a rectangle. As far as I know there is no safe
way to access the Cairo surface of a gtk3 DrawingArea other than through
the Cairo context pointer passed into the drawing event handler.
Following is some incomplete, stripped down code which may help to explain
the above ideas. I hope this helps!
Roger Davis
Univ. of Hawaii
######### code follows ###########
/* Here are the relevant parts of the Canvas structure */
typedef struct {
...
GtkWidget *drawarea; /* created by gtk_drawing_area_new() */
int width, height; /* size of DrawingArea */
cairo_surface_t *surface; /* my private Cairo surface */
...
} Canvas;
gboolean
canvasdrawevt(GtkWidget *w, cairo_t *cr, gpointer gp)
/*
This internal routine handles draw signals sent by GTK+3 to a Canvas'
GtkDrawingArea widget. These signals will typically be generated by
expose events or by program calls to gtk_widget_queue_draw_area()
generated from within canvasflushregion(). This routine merely copies
the rectangle(s) of interest from the off-screen Cairo drawing surface
of the canvas into the actual GtkDrawingArea widget.
*/
{
Canvas *c;
if (gp == (gpointer) 0)
return FALSE;
c= (Canvas *) gp;
if (w != c->drawarea)
return FALSE;
/* here I set the source to my private
surface which I have already drawn */
cairo_set_source_surface(cr, c->surface, 0, 0);
/* note that according to various (and occasionally obscure)
GTK+3 docs, the context cr passed into this routine has
already been clipped to any exposed rectangle(s) of interest
(or whatever canvasflush{reg}() has marked for redraw via
its call to gtk_widget_queue_draw_area()), so the following
call to copy the whole drawing surface is not as expensive
as it looks! */
cairo_rectangle(cr, 0, 0, (double) c->width, (double) c->height);
cairo_fill(cr);
return TRUE;
}
/* Here is how the important parts of the Canvas are created ... */
Canvas *
canvascreate(gint width, gint height, ... )
{
Canvas *c;
int i;
GtkWidget *win, *lo, *sw;
GdkGeometry geom;
if ((c= (Canvas *) calloc((MemSizeType) 1, sizeof(Canvas))) == (Canvas *) 0)
return (Canvas *) 0;
...
/* create the DrawingArea */
c->width= width;
c->height= height;
if ((c->drawarea= gtk_drawing_area_new()) == (GtkWidget *) 0) {
canvasdestroy(c);
return (Canvas *) 0;
}
gtk_widget_set_size_request(c->drawarea, width, height);
gtk_widget_set_can_focus(c->drawarea, TRUE);
...
/* attach the drawing event handler */
g_signal_connect((gpointer) c->drawarea, "draw", G_CALLBACK(canvasdrawevt), (gpointer) c);
...
/* create our private Cairo surface on which we will draw
everything */
if ((c->surface= cairo_image_surface_create(CAIRO_FORMAT_ARGB32, (int) width, (int) height)) ==
(cairo_surface_t *) 0) {
canvasdestroy(c);
return (GITCanvas *) 0;
}
...
return c;
}
/* Call this routine to copy our private Cairo surface to the DrawingArea
whenever we want (i.e., after we have done all our drawing into the
former). A call to this routine will result in our drawing event
handler above being called asynchronously at some later time (but
probably just about immediately). */
void
canvasflushregion(Canvas *c, int x0, int x1, int y0, int y1)
{
unsigned int w, h;
/* my real code checks x0/x1/y0/y1 for
correctness before proceeding! */
...
w= (unsigned int) (x1-x0+1);
h= (unsigned int) (y1-y0+1);
/* the following call will result in GTK+3/GDK sending a draw
signal on the rectangle of interest that will ultimately be
handled within canvasdrawevt(); see further comments there */
gtk_widget_queue_draw_area(c->drawarea, px0, py0, w, h);
return;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]