Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <gtk/gtk.h>
- #include <cairo.h>
- GtkWidget* window;
- GtkWidget* darea;
- gboolean full_redraw = FALSE;
- gboolean pressed = FALSE;
- GList* pts = NULL;
- cairo_surface_t* surfBuffer = NULL;
- void invalidate_all()
- {
- GdkRectangle rect;
- gtk_widget_get_allocation(darea, &rect);
- gdk_window_invalidate_rect(darea->window, &rect, TRUE);
- }
- void draw_stroke(cairo_t *cr)
- {
- cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
- cairo_set_source_rgba(cr, 1, 0, 0, 0.2);
- cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
- cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
- cairo_set_antialias(cr, CAIRO_ANTIALIAS_GOOD);
- cairo_set_line_width(cr, 5);
- GList *current = pts;
- GdkPoint *cur_pt = (GdkPoint *) current->data;
- cairo_move_to(cr, cur_pt->x, cur_pt->y);
- current = current->next;
- for(; current; current = current->next)
- {
- cur_pt = (GdkPoint *) current->data;
- cairo_line_to(cr, cur_pt->x, cur_pt->y);
- }
- cairo_stroke(cr);
- }
- static gboolean
- on_motion_event(GtkWidget *widget,
- GdkEvent *event,
- gpointer user_data)
- {
- if(!pressed)
- return TRUE;
- GdkPoint *pt = g_malloc(sizeof(GdkPoint));
- pt->x = ((GdkEventButton*)event)->x;
- pt->y = ((GdkEventButton*)event)->y;
- pts = g_list_append(pts, pt);
- invalidate_all();
- return TRUE;
- }
- static gboolean
- on_button_press_event(GtkWidget *widget, GdkEventButton *event)
- {
- if (event->button == 1)
- {
- pressed = TRUE;
- }
- return TRUE;
- }
- static gboolean
- on_button_release_event(GtkWidget *widget, GdkEventButton *event)
- {
- if (event->button == 1)
- {
- pressed = FALSE;
- if(full_redraw)
- {
- cairo_t *cr = cairo_create(surfBuffer);
- draw_stroke(cr);
- cairo_destroy(cr);
- invalidate_all();
- }
- g_list_free(pts);
- pts = NULL;
- }
- return TRUE;
- }
- static void
- on_size_allocate_event(GtkWidget *widget,
- GdkRectangle *allocation,
- gpointer user_data)
- {
- const gint size = 20;
- const gint w = allocation->width, h = allocation->height;
- if(surfBuffer)
- {
- cairo_surface_destroy(surfBuffer);
- surfBuffer = NULL;
- }
- surfBuffer = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
- w, h);
- cairo_t* cr = cairo_create(surfBuffer);
- // draw a test pattern to the surface...
- cairo_rectangle(cr, 0, 0, w, h);
- cairo_set_source_rgb(cr, 1, 1, 1);
- cairo_fill(cr);
- gint x = 5, y = 5;
- cairo_set_source_rgb(cr, 0.9, 0.9, 0.9);
- while(x + size < w)
- {
- while(y + size < h)
- {
- cairo_rectangle(cr, x, y, size, size);
- cairo_fill(cr);
- y += 5 + size;
- }
- y = 5;
- x += 5 + size;
- }
- cairo_destroy(cr);
- g_list_free(pts);
- pts = NULL;
- }
- static gboolean
- on_expose_event(GtkWidget *widget,
- GdkEventExpose *event,
- gpointer data)
- {
- cairo_t *cr;
- GtkAllocation alloc;
- if(!full_redraw && pts)
- {
- GList *last = g_list_last(pts);
- GList *bef = g_list_previous(last);
- if(last && bef)
- {
- cairo_t *crBuffer = cairo_create(surfBuffer);
- cairo_set_operator(crBuffer, CAIRO_OPERATOR_OVER);
- cairo_set_source_rgba(crBuffer, 1, 0, 0, 0.2);
- cairo_set_line_join(crBuffer, CAIRO_LINE_JOIN_ROUND);
- cairo_set_line_cap(crBuffer, CAIRO_LINE_CAP_ROUND);
- cairo_set_antialias(crBuffer, CAIRO_ANTIALIAS_GOOD);
- cairo_set_line_width(crBuffer, 5);
- GdkPoint *last_pt = (GdkPoint *) last->data;
- GdkPoint *bef_pt = (GdkPoint *) bef->data;
- cairo_move_to(crBuffer, bef_pt->x, bef_pt->y);
- cairo_line_to(crBuffer, last_pt->x, last_pt->y);
- cairo_stroke(crBuffer);
- cairo_destroy(crBuffer);
- }
- }
- gtk_widget_get_allocation(darea, &alloc);
- cr = gdk_cairo_create(darea->window);
- cairo_set_source_surface(cr, surfBuffer, 0, 0);
- cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
- cairo_rectangle(cr, 0, 0, alloc.width, alloc.height);
- cairo_fill(cr);
- if(!pts || !pressed)
- {
- cairo_destroy(cr);
- return TRUE;
- }
- if(full_redraw)
- {
- draw_stroke(cr);
- }
- cairo_destroy(cr);
- return TRUE;
- }
- int main(int argc, char **argv)
- {
- gtk_init(&argc, &argv);
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_default_size(GTK_WINDOW(window), 390, 240);
- darea = gtk_drawing_area_new();
- gtk_container_add(GTK_CONTAINER(window), darea);
- g_signal_connect(darea, "expose-event",
- G_CALLBACK(on_expose_event),
- NULL);
- g_signal_connect(darea, "motion-notify-event",
- G_CALLBACK(on_motion_event),
- NULL);
- g_signal_connect(darea, "button_press_event",
- G_CALLBACK(on_button_press_event),
- NULL);
- g_signal_connect(darea, "button_release_event",
- G_CALLBACK(on_button_release_event),
- NULL);
- g_signal_connect(darea, "size-allocate",
- G_CALLBACK(on_size_allocate_event),
- NULL);
- gtk_widget_set_events(darea, GDK_EXPOSURE_MASK
- | GDK_LEAVE_NOTIFY_MASK
- | GDK_BUTTON_PRESS_MASK
- | GDK_BUTTON_RELEASE_MASK
- | GDK_POINTER_MOTION_MASK
- | GDK_POINTER_MOTION_HINT_MASK);
- gtk_widget_show_all(window);
- gtk_main();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement