Re: porting gdk - cairo

2010-08-20 Thread Dov Grobgeld
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

2010-08-18 Thread Allin Cottrell
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

2010-08-17 Thread Dov Grobgeld
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

2010-08-11 Thread jcupitt
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

2010-08-11 Thread Jean-Philippe Chancelier

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

2010-08-11 Thread Allin Cottrell
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

2010-08-10 Thread Allin Cottrell
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

2010-08-10 Thread Dov Grobgeld
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

2010-08-10 Thread Allin Cottrell
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