Re: bug in Cairo or Gtk - peculiar behaviour on resizing or exposing window



On 13 November 2010 22:18, N James Bridge <james xmas demon co uk> wrote:
I am hoping someone will have the time to look at this. I have been
developing a gtk/cairo program to draw views of the Mandelbrot set. I
wanted to show how the usual iteration progressed for an arbitrary
starting point; it worked but occasionally seemed to misbehave. Below is
a cut-back version which illustrates the problem. A left click with the
mouse sets a starting point which behaves correctly; a right click sets
a nearby point which produces a very similar figure but which
misbehaves. To see this first try resizing the window - for some sizes
it is drawn correctly but for others not. With a bad version, slide
another window in front and then away to the side, when the picture is
redrawn correctly. Then try minimising it and restoring it, which makes
it go wrong again.
I am using gtk2-2.22.0-1.fc14.1.x86_64, cairo-1.10.0-2.fc14.x86_64 and
gcc-4.5.1-4.fc14.x86_64

So, first: have I done something wrong (probably in draw_iter())?

I can't see anything wrong exactly. I tried explicitly initializing z
in draw_iter with z.x = cc.x; z.y = cc.y, and used
gtk_widget_queue_draw instead of gdk_window_invalidate_rect but both
of these made no difference. I also added some printf statements to
check what's happening. For the values of cc, the code never returns
in the first for loop, and the values of z.x and z.y after both loops
never changes other than when cc does. In other words, the drawing may
change, but z.x and z.y after both loops does not. The next thing I'd
try would be to run it through valgrind but I need to reboot to do
that as valgrind is unusable on my current system.

james.

If not, is there a bug in gtk or gdk or cairo ?

Many thanks for any help

James Bridge

=======================================================================

/*  mbrot.c
   compile with:
   cc `pkg-config --cflags gtk+-2.0 --libs gtk+-2.0` mbrot.c -lm
*/

#include <gtk/gtk.h>
#include <math.h>

typedef struct {gdouble x, y;} complex_t;

GtkWidget *map;
complex_t cc = {0., 0.};

/******************************************************************************/

static gdouble step (complex_t* z, const complex_t* c);
void draw_iter (GtkWidget *area, const complex_t *c);
static void destroy( GtkWidget *widget, gpointer data );
static gboolean expose_event( GtkWidget *widget, GdkEventExpose *event,
                                                                               gpointer data );
static gboolean button_pressed (GtkWidget* widget, GdkEventButton*
event,
                               gpointer data);
static gboolean motion_notify (GtkWidget* map, GdkEventMotion* event,
                                GtkLabel *z_label);

/******************************************************************************/

static gdouble step (complex_t* z, const complex_t* c)
{
  gdouble xsq = z->x * z->x;
  gdouble ysq = z->y * z->y;
  z->y = 2 * z->x * z->y + c->y;
  z->x = xsq - ysq + c->x;
  return xsq + ysq;
}

/******************************************************************************/

void draw_iter (GtkWidget *area, const complex_t *c)
{
       GtkAllocation alloc;
       gtk_widget_get_allocation (area, &alloc);
       gdouble scale = 3.5 / alloc.width;

       gint n;
       gdouble r;
       complex_t z = cc;
       cairo_t *cra = gdk_cairo_create (gtk_widget_get_window (area));
       cairo_translate (cra, 0.5, 0.5);
  cairo_set_source_rgb (cra, .2, .2, .2);
  cairo_set_line_width (cra, 1.0);
  cairo_move_to (cra, (z.x + 2.5) / scale, - (z.y - 1.4) / scale);
  for (n = 0; n < 70; n++)

     if ((r = step (&z, c)) > 9.0)
       return;
  for (; n < 100; n++)
  {
     if ((r = step (&z, c)) > 9.0)
       break;
     cairo_line_to (cra, (z.x + 2.5) / scale, - (z.y - 1.4) / scale);
   }
  cairo_stroke (cra);
  cairo_destroy (cra);
  return;
}

/******************************************************************************/

static void destroy( GtkWidget *widget, gpointer data )
{
  gtk_main_quit ();
}

/******************************************************************************/

static gboolean
expose_event( GtkWidget *area, GdkEventExpose *event, gpointer data )
{
       if (cc.x != 0)
               draw_iter (area, &cc);

return FALSE;
}

/******************************************************************************/

static gboolean button_pressed (GtkWidget* map, GdkEventButton* event,
                                gpointer data)
{
       if (event->button == 1)
       {
               cc.x = -.99439;
               cc.y = 0.2626584;

       gdk_window_invalidate_rect (gtk_widget_get_window (map), NULL,
FALSE);
       }
       else if (event->button == 3)
  {
               cc.x = -.99063;
               cc.y = 0.26797;

       gdk_window_invalidate_rect (gtk_widget_get_window (map), NULL,
FALSE);
       }
  return FALSE;
}

/******************************************************************************/

gint main (gint argc, char* argv[])
{
  GtkWidget *window, *vbox, *hbox, *z_label, *start_button;
  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  map = gtk_drawing_area_new ();
  gtk_widget_set_can_focus (map, TRUE);
  gtk_widget_set_size_request (map, 500, 400);
  gtk_widget_add_events (map, GDK_BUTTON_PRESS_MASK );
  gtk_container_add (GTK_CONTAINER (window), map);
  g_signal_connect (G_OBJECT (window), "delete-event",
                    G_CALLBACK (destroy), NULL);
  g_signal_connect (G_OBJECT (map), "expose-event",
                    G_CALLBACK (expose_event), NULL);
  g_signal_connect (G_OBJECT (map), "button-press-event",
                    G_CALLBACK (button_pressed), NULL);
  gtk_widget_show_all (window);
  gtk_main ();
  return 0;
}
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list gnome org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list




-- 
_
: http://jwm-art.net/
-audio/image/text/code/



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