1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
/* Un exemple pour tracer un segment elastique <<à la Gimp>>:
*
* Tracer une ligne noire épaisse et une ligne blanche par dessus
* en rafraichissant l'image de fond à chaque déplacement de la souris.
*
* Compiler avec ( -lX11 avec la Xlib only)
* Pour GTK-2
* gcc -g -Wall `pkg-config --cflags gtk+-2.0` segment_elastique.c `pkg-config --libs gtk+-2.0` -lX11
* et GTK-3
* gcc -g -Wall `pkg-config --cflags gtk+-3.0` segment_elastique.c `pkg-config --libs gtk+-3.0` -lX11
*/
#include <math.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <cairo.h>
/* Taille de la fenêtre en pixels */
static int ix = 800;
static int iy = 500;
static GdkDisplay *gg_disp;
static GtkWidget *w_main_window ,*w_canvas;
static GdkWindow *gg_win;
static cairo_surface_t *surf_ecran;
static cairo_surface_t *surf_fond;
static int button_pressed = FALSE;
static gdouble x_init ,y_init;
//A26 static gdouble old_x ,old_y;
#define MIN2(a, b) (((a) < (b)) ? a : b)
#define MAX2(a, b) (((a) > (b)) ? a : b)
/*
* On affiche l'image de fond
*/
#if (GTK_MAJOR_VERSION == 2)
gboolean ev_expose (GtkWidget *w ,GdkEventExpose *event ,gpointer data)
{
cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (w_canvas));
cairo_set_source_surface (cr ,surf_fond ,0 ,0);
cairo_paint (cr);
cairo_destroy (cr);
return TRUE;
}
#else
gboolean ev_draw (GtkWidget *w ,cairo_t *cr ,gpointer data)
{
cairo_set_source_surface (cr ,surf_fond ,0 ,0);
cairo_paint (cr);
return TRUE;
}
#endif
/*
* Restore l'image de fond initiale
*/
void restore_fond (cairo_t *cr ,gdouble x ,gdouble y)
{
/* UNE TENTATIVE D'UTILISER UN RECTANGLE DE CLIP */
//A26 gdouble x0 = x_init - 2.0;
//A26 gdouble y0 = y_init - 2.0;
//A26 gdouble dx = (x - x_init) + 4.0;
//A26 gdouble dy = (y - y_init) + 4.0;
//A26
//A26 printf ("restore_fond: x0=%g dx=%g x=%g y0=%g dy =%g y=%g\n" ,x0 ,dx ,x ,y0 ,dy ,y);
//A26
//A26 CE CLIPPING NE MARCHE PAS POUR LA DIRECTION VERTICALE
//A26 cairo_rectangle (cr ,x0 ,y0 ,dx ,dy);
//A26 cairo_clip (cr);
cairo_set_source_surface (cr ,surf_fond ,0 ,0);
cairo_paint (cr);
//A26 cairo_reset_clip (cr);
}
void draw_line (cairo_t *cr ,gdouble x ,gdouble y)
{
cairo_set_line_width (cr ,3.0); /* large black line */
cairo_set_source_rgba (cr ,0.0 ,0.0 ,0.0 ,1.0);
cairo_move_to (cr ,x_init ,y_init);
cairo_line_to (cr ,x ,y);
cairo_stroke (cr);
cairo_set_line_width (cr ,1.0); /* thin white line */
cairo_set_source_rgba (cr ,1.0 ,1.0 ,1.0 ,1.0);
cairo_move_to (cr ,x_init ,y_init);
cairo_line_to (cr ,x ,y);
cairo_stroke (cr);
}
/*
* Reponses aux actions avec la souris
*/
/* Draw the line on w_canvas */
gint ev_button_press (GtkWidget *w ,GdkEvent *event ,gpointer data)
{
gdouble x = event->button.x;
gdouble y = event->button.y;
cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (w_canvas));
x_init = x;
y_init = y;
draw_line (cr ,x ,y);
//A26 old_x = x;
//A26 old_y = y;
cairo_destroy (cr);
button_pressed = TRUE;
return TRUE;
}
/* redraw surf_fond without the line */
gint ev_button_release (GtkWidget *w ,GdkEvent *event ,gpointer data)
{
cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (w_canvas));
restore_fond (cr ,((GdkEventMotion *)event)->x ,((GdkEventMotion *)event)->y);
cairo_destroy (cr);
button_pressed = FALSE;
return TRUE;
}
int ev_pointer_motion (GtkWidget *w ,GdkEventMotion *event ,gpointer data)
{
if (button_pressed ) {
cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (w_canvas));
restore_fond (cr ,((GdkEventMotion *)event)->x ,((GdkEventMotion *)event)->y);
draw_line (cr ,event->x ,event->y);
cairo_destroy (cr);
}
return TRUE;
}
/*
* Programme principal
*/
int main( int argc ,char *argv[] )
{
gdouble w ,h ,dx ,dy;
cairo_t *cr;
gtk_init (&argc ,&argv);
printf ("GTK_MAJOR_VERSION = %d\n" ,GTK_MAJOR_VERSION);
printf ("GTK_MINOR_VERSION = %d\n" ,GTK_MINOR_VERSION);
w_main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gg_disp = gdk_display_get_default ();
w_canvas = gtk_drawing_area_new ();
gtk_widget_set_size_request (w_main_window ,ix ,iy);
gtk_container_add (GTK_CONTAINER (w_main_window) ,w_canvas );
gtk_widget_add_events (w_canvas
, GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
| GDK_POINTER_MOTION_MASK
);
gtk_widget_show_all (w_main_window);
gg_win = gtk_widget_get_window (w_canvas);
#if (GTK_MAJOR_VERSION == 2)
g_signal_connect (w_canvas ,"expose_event" ,G_CALLBACK (ev_expose) ,NULL);
#else
g_signal_connect (w_canvas ,"draw" ,G_CALLBACK (ev_draw) ,NULL);
#endif
g_signal_connect (w_canvas ,"button-press-event" ,G_CALLBACK (ev_button_press) ,NULL);
g_signal_connect (w_canvas ,"button-release-event" ,G_CALLBACK (ev_button_release) ,NULL);
g_signal_connect (w_canvas ,"motion-notify-event" ,G_CALLBACK (ev_pointer_motion) ,NULL);
g_signal_connect (w_main_window ,"delete_event" ,G_CALLBACK (gtk_main_quit) ,NULL);
gtk_widget_show_all (w_main_window);
/* Creation de surf_fond, le buffer pour l'image de fond */
cr = gdk_cairo_create (gtk_widget_get_window (w_canvas));
surf_ecran = cairo_get_target (cr);
surf_fond = cairo_surface_create_similar (surf_ecran ,CAIRO_CONTENT_COLOR_ALPHA ,ix ,iy);
cairo_destroy (cr);
/* on dessine le fond dans surf_fond */
w = (gdouble)ix;
h = (gdouble)iy;
cr = cairo_create (surf_fond);
/* set the background color */
cairo_set_source_rgb (cr ,1.0 ,1.0 ,1.0);
cairo_rectangle (cr ,0 ,0 ,w ,h);
cairo_fill (cr);
dx = w / 6.0;
dy = h / 6.0;
/* rectangle noir */
cairo_set_source_rgb (cr ,0.0 ,0.0, 0.0);
cairo_rectangle (cr ,dx ,dy ,dx ,dy);
cairo_fill (cr);
/* cercle rouge */
cairo_set_source_rgb (cr ,1.0 ,0.0, 0.0);
cairo_arc (cr ,3*dx ,1.5*dy ,dx/2.0 ,0.0 ,6.2831853);
cairo_fill (cr);
/* cercle vert */
cairo_set_source_rgb (cr ,0.0 ,1.0, 0.0);
cairo_arc (cr ,1.5*dx ,3*dy ,dx/2.0 ,0.0 ,6.2831853);
cairo_fill (cr);
/* rectangle bleu */
cairo_set_source_rgb (cr ,0.0 ,0.0, 1.0);
cairo_rectangle (cr ,2.5*dx ,2.5*dy ,dx ,dy);
cairo_fill (cr);
/* on copie l'image dans surf_fond */
cairo_set_source_surface (cr ,surf_fond ,0 ,0);
cairo_paint (cr);
cairo_destroy (cr);
gtk_main ();
return 0;
} |
Partager