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())? 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