Re: How to improve performance of this example?



Thank you Richard, the code you wrote works for me and it gave me
ideas on how to re-structure mine.

2011/7/23 richard boaz <ivor boaz gmail com>:
> hi,
> the problem isn't the mouse going "too fast" (this is "not possible", if it
> can go fast, it can), it's that you're wanting to draw a line using points.
> drawing a real line between the last point received by the drag event and
> the new/next point will get you what you want, example code below.
> and to answer your question, yes it can be made more efficient.
> cheers,
> richard
> p.s. be careful re: your callback parameters, your drag function defined the
> 2nd argument wrong.
> ======== BEGIN CODE EXAMPLE ========
> #include <string.h>
> #include <gtk/gtk.h>
> enum {
> MOUSE_CLICK,
> MOUSE_DRAG,
> TTL_MOUSE_EVENTS
> };
> static inline void brush(cairo_t *cr, double x1, double y1, double x2,
> double y2)
> {
> cairo_move_to(cr, x1, y1);
> cairo_line_to(cr, x2, y2);
> cairo_stroke(cr);
> }
> static gboolean handle_mouse(GtkWidget *widget, void *e, gpointer *t)
> {
> static struct {
> gboolean isdragging;
> cairo_t *cr;
> double x, y;
> } mouseState;
> gint type = GPOINTER_TO_INT(t);
> switch(type)
> {
> case MOUSE_CLICK:
> {
> GdkEventButton *event = (GdkEventButton*) e;
> switch(event->type)
> {
> case GDK_BUTTON_PRESS:
> {
> mouseState.isdragging = TRUE;
> mouseState.cr = gdk_cairo_create(widget->window);
> cairo_set_source_rgb(mouseState.cr, 0, 0, 0);
> cairo_set_line_width(mouseState.cr, 2);
> mouseState.x = event->x; mouseState.y = event->y;
> }
> break;
> case GDK_BUTTON_RELEASE:
> {
> cairo_destroy(mouseState.cr);
> memset(&mouseState, 0, sizeof(mouseState));
> }
> break;
> default:
> break;
> }
> }
> break;
> case MOUSE_DRAG:
> {
> GdkEventMotion *event = (GdkEventMotion*) e;
> static GdkWindow *gdkWindow;
> if (!gdkWindow)
> { // initialize
> gdkWindow = gdk_get_default_root_window();
> memset(&mouseState, 0, sizeof(mouseState));
> return TRUE;
> }
> if (!mouseState.isdragging ||
>     (mouseState.x == event->x && mouseState.y == event->y))
> return TRUE;
> brush(mouseState.cr, mouseState.x, mouseState.y, event->x, event->y);
> mouseState.x = event->x; mouseState.y = event->y;
> {
> // even though we don't use the resulting information from this call,
> // calling it is an indication to the main_loop()
> // that we are ready to receive the next mouse motion notify event
> gint x, y;
> GdkModifierType state;
> gdk_window_get_pointer(gdkWindow, &x, &y, &state);
> }
> }
> break;
> default:
> break;
> }
> return TRUE;
> }
> int main( int argc,
>           char *argv[] )
> {
>   GtkWidget *window;
>   GtkWidget *main_vbox;
>   gtk_init (&argc, &argv);
>
>   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
>   gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC
> (gtk_main_quit), "WM destroy");
>   gtk_widget_set_usize (GTK_WIDGET(window), 300, 200);
>
>   main_vbox = gtk_vbox_new (FALSE, 1);
>   gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
>   gtk_container_add (GTK_CONTAINER (window), main_vbox);
>   gtk_widget_show (main_vbox);
>
>   //gtkdrawable + cairo
>   GtkWidget *canvas = gtk_drawing_area_new();
>   gtk_widget_set_size_request (canvas, 500, 600);
>
>   //gtk_widget_add_events(canvas, GDK_BUTTON_PRESS_MASK);
>   gtk_widget_add_events(canvas, GDK_ALL_EVENTS_MASK);
>   g_signal_connect(canvas, "button-press-event", G_CALLBACK(handle_mouse),
> GINT_TO_POINTER(MOUSE_CLICK));
>   g_signal_connect(canvas, "button-release-event", G_CALLBACK(handle_mouse),
> GINT_TO_POINTER(MOUSE_CLICK));
>   g_signal_connect(canvas, "motion-notify-event",G_CALLBACK(handle_mouse),
> GINT_TO_POINTER(MOUSE_DRAG));
>   gtk_box_pack_start (GTK_BOX (main_vbox), canvas, FALSE, TRUE, 0);
>
>   //ends gtkdrawable + cairo example
>   gtk_widget_show_all (window);
>   gtk_main ();
>
>   return(0);
> }
> ======== END CODE EXAMPLE ========
> 2011/7/23 Carlos López Camey <c lopez kmels net>
>>
>> Hello, I'm new to the list, GTK+ and C. I'm building a Paint-like
>> application and was trying how to simulate the Brush tool with an
>> example to see how it performs. I read about GtkImage, GtkBitmap and
>> GtkPixmap but was recommended in #gtk+ over at irc.gnome.org to use a
>> GtkDrawingArea + Cairo since in GTK3 some of these were deprecated,
>> and it's encouraged to use cairo surfaces instead.
>>
>> The problem with my example is, when you click and "brush" with the
>> mouse moving *too fast*, the signal doesn't come fast enough. What
>> could/would be faster? using pixbufs + GtkImage? I couldn't find
>> enough documentation about that, but that's why I am asking :)
>>
>> Here's what I got (or if you prefer http://paste.pocoo.org/show/444721/)
>>
>> Thank you!
>>
>> ----- canvas-test.c ------
>> #include <gtk/gtk.h>
>>
>> int isdragging = 0;
>>
>> /* Brush, paints a single pixel in coordinate x,y*/
>> void brush(cairo_t *cr, double x, double y){
>>  cairo_set_source_rgb(cr, 0, 0, 0);
>>  cairo_set_line_width (cr, 1);
>>  cairo_rectangle(cr,x,y,1,1);
>>  cairo_stroke(cr);
>>  cairo_destroy(cr);
>> }
>>
>> gboolean handle_mouse_click(GtkWidget *widget, GdkEventButton *event,
>> gpointer user_data){
>>  brush(gdk_cairo_create(widget->window), event->x, event->y);
>>  isdragging = 1;
>>  return TRUE;
>> }
>>
>> gboolean handle_mouse_release(GtkWidget *widget, GdkEventButton
>> *event, gpointer user_data){
>>  if (event->button == 1) {
>>    isdragging = 0;
>>  }
>>
>>  return TRUE;
>> }
>>
>> gboolean handle_mouse_drag(GtkWidget *widget, GdkEventButton *event,
>> gpointer user_data){
>>  if (isdragging)
>>    brush(gdk_cairo_create(widget->window), event->x, event->y);
>>  return TRUE;
>> }
>>
>> int main( int argc,
>>          char *argv[] )
>> {
>>  GtkWidget *window;
>>  GtkWidget *main_vbox;
>>
>>  gtk_init (&argc, &argv);
>>
>>  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
>>  gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC
>> (gtk_main_quit), "WM destroy");
>>  gtk_widget_set_usize (GTK_WIDGET(window), 300, 200);
>>
>>  main_vbox = gtk_vbox_new (FALSE, 1);
>>  gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
>>  gtk_container_add (GTK_CONTAINER (window), main_vbox);
>>  gtk_widget_show (main_vbox);
>>
>>  //gtkdrawable + cairo
>>  GtkWidget *canvas = gtk_drawing_area_new();
>>  gtk_widget_set_size_request (canvas, 500, 600);
>>
>>  //gtk_widget_add_events(canvas, GDK_BUTTON_PRESS_MASK);
>>  gtk_widget_add_events(canvas, GDK_ALL_EVENTS_MASK);
>>  g_signal_connect(canvas, "button-press-event",
>> G_CALLBACK(handle_mouse_click), NULL);
>>  g_signal_connect(canvas, "button-release-event",
>> G_CALLBACK(handle_mouse_release), NULL);
>>  g_signal_connect(canvas,
>> "motion-notify-event",G_CALLBACK(handle_mouse_drag), NULL);
>>
>>  gtk_box_pack_start (GTK_BOX (main_vbox), canvas, FALSE, TRUE, 0);
>>
>>  //ends gtkdrawable + cairo example
>>  gtk_widget_show_all (window);
>>  gtk_main ();
>>
>>  return(0);
>> }
>> _______________________________________________
>> gtk-list mailing list
>> gtk-list gnome org
>> http://mail.gnome.org/mailman/listinfo/gtk-list
>
>


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