Re: porting gdk - cairo
I took the bait and coded my solution that I (in lack of anything better called) dovtk-lasso . I'm including it below including a test program. I think this solution is even simpler than your old xor solution. All you need to do is to create the draw_callback fuction that uses whatever cairo painting you want to draw your overlay. Note that this function is called twice, once to extract where you are drawing, and once to do the drawing. During the first time the do_mask variable is on. In this case you should choose a thicker pen and draw in black, to make sure that everything is included. Note that there is one constraint that I have not been able to solve. The expose-event callback that is doing the actual drawing of your graphics have to return FALSE. I would be happy to receive a solution for it. I promise to put this code into git-hub as soon as possible. //== // test-gtk-lasso.c - This example is in the public domain // // Dov Grobgeld dov.grobg...@gmail.com // Mon Aug 16 09:09:56 2010 //-- #include stdlib.h #include gtk/gtk.h #include math.h #include dovtk-lasso.h DovtkLasso *lasso = NULL; int start_x, start_y, end_x, end_y; int cb_expose(GtkWidget *widget, GdkEventExpose *event, gpointeruser_data) { cairo_t *cr; cr = gdk_cairo_create(widget-window); cairo_rectangle(cr, event-area.x, event-area.y, event-area.width, event-area.height); cairo_clip(cr); // Just draw anything in the widget double x, y; x = widget-allocation.x + widget-allocation.width / 2; y = widget-allocation.y + widget-allocation.height / 2; double radius; radius = MIN (widget-allocation.width / 2, widget-allocation.height / 2) - 5; cairo_set_source_rgb(cr, 0,0,0); cairo_arc (cr, x, y, radius, 0, 2 * M_PI); cairo_stroke(cr); cairo_destroy(cr); return FALSE; } /** * Draw whatever overlay you want on the image. If the do_mask * is on, then you should paint in black and with a pen that * is thicker than the drawing. */ void my_lasso_draw(cairo_t *cr, gboolean do_mask, // output DovtkLassoRectangleList **rect_list) { int min_x = MIN(start_x, end_x); int min_y = MIN(start_y, end_y); if (!do_mask) { cairo_set_source_rgb(cr, 1,0,0); cairo_set_line_width(cr,1); } else cairo_set_line_width(cr, 5); cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); // Draw a rectangle cairo_rectangle(cr, min_x, min_y, abs(end_x-start_x), abs(end_y-start_y)); cairo_stroke(cr); } int cb_button_press(GtkWidget *widget, GdkEventButton *event, gpointeruser_data) { lasso = dovtk_lasso_create(widget, my_lasso_draw, TRUE); start_x = event-x; start_y = event-y; return FALSE; } int cb_button_release(GtkWidget *widget, GdkEventButton *event, gpointeruser_data) { dovtk_lasso_destroy(lasso); lasso = NULL; return FALSE; } int cb_motion_notify(GtkWidget *widget, GdkEventMotion *event, gpointeruser_data) { //printf(button motion\n); end_x = event-x; end_y = event-y; dovtk_lasso_update(lasso); return FALSE; } int main(int argc, char *argv[]) { gtk_init(argc, argv); GtkWidget *w_top = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(w_top), delete-event, G_CALLBACK(gtk_main_quit), NULL); GtkWidget *w_draw = gtk_drawing_area_new(); gtk_container_add(GTK_CONTAINER(w_top), w_draw); gtk_widget_set_size_request(w_draw, 500,500); g_signal_connect(G_OBJECT(w_draw), expose-event, G_CALLBACK(cb_expose), NULL); // TBD - set up events for lasso gtk_widget_add_events(w_draw, GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); g_signal_connect(G_OBJECT(w_draw), button-press-event, G_CALLBACK(cb_button_press), NULL); g_signal_connect(G_OBJECT(w_draw), button-release-event, G_CALLBACK(cb_button_release), NULL); g_signal_connect(G_OBJECT(w_draw), motion-notify-event, G_CALLBACK(cb_motion_notify), NULL); gtk_widget_show_all(w_top); gtk_main(); return 0; } /** * dovtk-lasso.h * * A solution for drawing overlays on a gtk widget. * * This code is relased under the LGPL
Re: porting gdk - cairo
On Wed, 18 Aug 2010, Dov Grobgeld wrote: I don't know if you noticed it in another thread, but I created a working example of the approach that I described in my earlier email. See: http://github.com/dov/dovtk-lasso See the program test-dovtk-lasso.c for an example of how to use it. Thanks. Yes, I did notice the discussion and I'll take a look at the code. Allin Cottrell ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: porting gdk - cairo
I don't know if you noticed it in another thread, but I created a working example of the approach that I described in my earlier email. See: http://github.com/dov/dovtk-lasso See the program test-dovtk-lasso.c for an example of how to use it. Please let me know if you need more explanations. The source code isn't very well documented yet. Regards, Dov On Wed, Aug 11, 2010 at 20:12, Allin Cottrell cottr...@wfu.edu wrote: On Wed, 11 Aug 2010 jcup...@gmail.com wrote: On 11 August 2010 02:14, Allin Cottrell cottr...@wfu.edu wrote: rid of GdkGC. I'd imagine that the effect I'm after is something that many GTP apps have need of, and it's trivial to achieve with the GDK API. I've found that XOR rubber banding is quite hard to do reliably in gdk. The problem I think is that you are using the screen pixels to store part of the state, and that gets hard to coordinate between the various things that can affect the display. I had mouse movements triggering rect moves, mouse moves with a button held down causing background scrolling of the canvas, and mouse moves over other screen objects triggering highlight effects. With all these things going on at once it became very difficult to get XOR rubber bands to not leave annoying trails as they moved. I switched to an update-model / invalidate-widget / redraw-on-idle scheme as Dov suggests and I got prettier updates with less complication. Since input and output are decoupled, it'll scale more gracefully between slower and faster machines as well, which is nice. My drawing case may be simpler than yours -- there's nothing scrollable in the vicinity -- but I've found that rubber-banding using GDK_INVERT to undraw the last box works flawlessly at low programming cost. But can you suggest a good example to look at for the alternative approach? Thanks. Allin Cottrell ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: porting gdk - cairo
On 11 August 2010 02:14, Allin Cottrell cottr...@wfu.edu wrote: rid of GdkGC. I'd imagine that the effect I'm after is something that many GTP apps have need of, and it's trivial to achieve with the GDK API. I've found that XOR rubber banding is quite hard to do reliably in gdk. The problem I think is that you are using the screen pixels to store part of the state, and that gets hard to coordinate between the various things that can affect the display. I had mouse movements triggering rect moves, mouse moves with a button held down causing background scrolling of the canvas, and mouse moves over other screen objects triggering highlight effects. With all these things going on at once it became very difficult to get XOR rubber bands to not leave annoying trails as they moved. I switched to an update-model / invalidate-widget / redraw-on-idle scheme as Dov suggests and I got prettier updates with less complication. Since input and output are decoupled, it'll scale more gracefully between slower and faster machines as well, which is nice. Anyway, my 2p. John ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: porting gdk - cairo
Allin (in response to my query about drawing a resizable outline rectangle Allin on top of an image displayed in a GTK window, using cairo instead of Allin the GDK drawing API) I have a naive question about the port gdk - cairo. Is the cairo port drawing supposed to be as fast as the gdk cairo drawing ? I have an application which can perform graphics (graphs, surfaces) through cairo or gdk or gtkglext and I have experienced that using cairo is really slower compared to gdk. I would have liked to know is this is only a side effect of my implementation or a general fact. jpc ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: porting gdk - cairo
On Wed, 11 Aug 2010 jcup...@gmail.com wrote: On 11 August 2010 02:14, Allin Cottrell cottr...@wfu.edu wrote: rid of GdkGC. I'd imagine that the effect I'm after is something that many GTP apps have need of, and it's trivial to achieve with the GDK API. I've found that XOR rubber banding is quite hard to do reliably in gdk. The problem I think is that you are using the screen pixels to store part of the state, and that gets hard to coordinate between the various things that can affect the display. I had mouse movements triggering rect moves, mouse moves with a button held down causing background scrolling of the canvas, and mouse moves over other screen objects triggering highlight effects. With all these things going on at once it became very difficult to get XOR rubber bands to not leave annoying trails as they moved. I switched to an update-model / invalidate-widget / redraw-on-idle scheme as Dov suggests and I got prettier updates with less complication. Since input and output are decoupled, it'll scale more gracefully between slower and faster machines as well, which is nice. My drawing case may be simpler than yours -- there's nothing scrollable in the vicinity -- but I've found that rubber-banding using GDK_INVERT to undraw the last box works flawlessly at low programming cost. But can you suggest a good example to look at for the alternative approach? Thanks. Allin Cottrell ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
porting gdk - cairo
I gather from recent discussion on the gtk-devel list that a good deal of the old GDK drawing API may be removed for GTK 3 in favor of use of cairo: in particular GdkGC seems likely to disappear. There appear to be good arguments for this, but it means some extra work for people trying to get their apps GTK3-ready. Benjamin Otte has some notes on porting at http://blogs.gnome.org/otte/2010/07/27/rendering-cleanup/ but there's one piece of GDK code I've been using for which I can't figure out the cairo equivalent and I wonder if anyone can help. The context is zooming to a selected portion of a graphic displayed in a GTK window. If the user selects a Zoom menu item she can then drag out a rectangular outline on the current image, and when the mouse button is released the view snaps to the chosen rectangle. The tricky part is avoiding a horrible mess as the user drags the rectangle. This is achieved via a cycle of draw-display-erase as the mouse pointer moves. In GDK, the erase part is done by redrawing the last-shown rectangle using an inverted GdkGC: gdk_gc_set_function(gc, GDK_INVERT); How would you do this in cairo? Thanks. -- Allin Cottrell Department of Economics Wake Forest University ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: porting gdk - cairo
The following solution does the job though it causes flickering. - If there is a previous backing store (see below) then restore it to the underlying image. - Define the rectangle to draw by the button-press and the motion-notify-events. - Copy the four edges of below the rectangle to four GdkPixmaps, that I call backing store. - Draw the rectangle. The following more complex solution should take care of flickering: Preparation: - Create an expose handle that is called after the default expose handle which uses cairo to draw a rectangle in coordinates determined by structure R (see below). Note that this expose handle will be called up to eight times every time a motion notify event occurs. - Create a fifo buffer containing up to eight CairoRectangles to be exposed. During motion: - Define the new rectangle to draw by button-press and motion-notify events and store it in the structure R available by the expose handle. - Push four areas corresponding to the four edges of the rectangles to the fifo buffer. - Expose the eight areas in the fifo buffer. - Pop off the first four areas of the fifo buffer. This solution relies on the underlying expose handle. If that expose handle is slow (e.g. complex vector graphics), the solution may be made faster by initiating the process (e.g. at button-press) by copying the entire widget window to an off screen pixmap, and then block the underlying expose handle. I'd be interested if there is a more compact solution. Regards, Dov On Tue, Aug 10, 2010 at 17:16, Allin Cottrell cottr...@wfu.edu wrote: I gather from recent discussion on the gtk-devel list that a good deal of the old GDK drawing API may be removed for GTK 3 in favor of use of cairo: in particular GdkGC seems likely to disappear. There appear to be good arguments for this, but it means some extra work for people trying to get their apps GTK3-ready. Benjamin Otte has some notes on porting at http://blogs.gnome.org/otte/2010/07/27/rendering-cleanup/ but there's one piece of GDK code I've been using for which I can't figure out the cairo equivalent and I wonder if anyone can help. The context is zooming to a selected portion of a graphic displayed in a GTK window. If the user selects a Zoom menu item she can then drag out a rectangular outline on the current image, and when the mouse button is released the view snaps to the chosen rectangle. The tricky part is avoiding a horrible mess as the user drags the rectangle. This is achieved via a cycle of draw-display-erase as the mouse pointer moves. In GDK, the erase part is done by redrawing the last-shown rectangle using an inverted GdkGC: gdk_gc_set_function(gc, GDK_INVERT); How would you do this in cairo? Thanks. -- Allin Cottrell Department of Economics Wake Forest University ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: porting gdk - cairo
On Tue, 10 Aug 2010, Dov Grobgeld wrote: (in response to my query about drawing a resizable outline rectangle on top of an image displayed in a GTK window, using cairo instead of the GDK drawing API) The following solution does the job though it causes flickering. - If there is a previous backing store (see below) then restore it to the underlying image. - Define the rectangle to draw by the button-press and the motion-notify-events. - Copy the four edges of below the rectangle to four GdkPixmaps, that I call backing store. - Draw the rectangle. The following more complex solution should take care of flickering: Preparation: - Create an expose handle that is called after the default expose handle which uses cairo to draw a rectangle in coordinates determined by structure R (see below). Note that this expose handle will be called up to eight times every time a motion notify event occurs. - Create a fifo buffer containing up to eight CairoRectangles to be exposed. During motion: - Define the new rectangle to draw by button-press and motion-notify events and store it in the structure R available by the expose handle. - Push four areas corresponding to the four edges of the rectangles to the fifo buffer. - Expose the eight areas in the fifo buffer. - Pop off the first four areas of the fifo buffer. This solution relies on the underlying expose handle. If that expose handle is slow (e.g. complex vector graphics), the solution may be made faster by initiating the process (e.g. at button-press) by copying the entire widget window to an off screen pixmap, and then block the underlying expose handle. I'd be interested if there is a more compact solution. Thanks very much for your thoughts on this. It seems to me that what you're describing is a rather complex workaround for missing functionality in cairo. I hope that the GTK developers will ensure that there's a reasonable way of doing this sort of thing in cairo before getting rid of GdkGC. I'd imagine that the effect I'm after is something that many GTP apps have need of, and it's trivial to achieve with the GDK API. Allin Cottrell ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list