Cairo drawing on top of a pixbuf or image

Hi,
I’m using Gtk 3.2 on Ubuntu 18.04.1 LTS with C language. I want to load and display a photograph and then do cairo lines, points and text over the top of the photo image without actually altering it. So far I have opened a photo in Photoshop and saved it as a .png file, then have used:

GdkPixbuf *image1;
GtkTextIter line;
image1 = gdk_pixbuf_new_from_file("landsend1.png", NULL);
gtk_text_buffer_get_iter_at_line(buffer_textview1_coords, &line, 0);
gtk_text_buffer_insert_pixbuf(buffer_textview1_coords, &line, image1);

to put it into a textview. This shows it but I can’t do cairo drawing on it. Can I somehow get it into a gtk_drawing_area()? Do I need to use GdkWindow and gdk_functions? My last attempt looks like this:

cairo_surface_t *surface = cairo_image_surface_create_from_png("photo1.png");
cr = cairo_create(surface);
gtk_render_background (context, cr, 0, 0, x_length, y_width_filz);
cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
cairo_paint(cr);

This compiles but the drawing area is blank, whereas if the above-mentioned is commented then another pre-existing text string is drawn with cairo_show_text(cr, str_text), showing the text-string is being overwritten by a blank something, I don’t know by what. Any help would be greatly appreciated, thanks,
Roger.

Yes, you need https://developer.gnome.org/gtk3/stable/GtkDrawingArea.html

And gdk_cairo_set_source_pixbuf().

In our project, we have an example mixing cairo vectorial drawing and a pixbuf:

...
    call cairo_move_to(my_cairo_context, 60d0, 0d0)  
    call cairo_curve_to(my_cairo_context, 600d0, 50d0, 135d0, 45d0, 500d0, 500d0)
    call cairo_stroke(my_cairo_context) 

    call gdk_cairo_set_source_pixbuf(my_cairo_context, my_pixbuf, 700d0/4d0, 700d0/4d0) 
    call cairo_paint(my_cairo_context)

    call cairo_set_source_rgb(my_cairo_context, 1d0, 1d0, 0d0)
    call cairo_set_line_width(my_cairo_context, 2d0)
    call cairo_move_to(my_cairo_context, 0d0, height/2d0)  
...

See the whole file: gtk-fortran/cairo-tests.f90 at gtk3 · vmagnin/gtk-fortran · GitHub

https://developer.gnome.org/gdk3/stable/gdk3-Cairo-Interaction.html#gdk-cairo-set-source-pixbuf

Hi Vincent, here is the full code including my unsuccessful attempt, with your suggestion, it compiles and runs but doesn’t show the image, only some text and a cairo line. You will need to put a .png file into the working directory and it can be compiled with:

gcc -rdynamic -Wall `pkg-config --cflags gtk+-3.0` -o filename filename.c `pkg-config --libs gtk+-3.0`
#include <stdio.h>
#include <gtk/gtk.h>

#define WINDOW_ISIZE 1200
#define WINDOW_JSIZE 720

 struct main_struct
 {
 GtkWidget *da_filz, *window;
 };

 void app_activate(GtkApplication *app, struct main_struct *stuff);
 gboolean draw_filz(GtkWidget *da_filz, cairo_t *cr, struct main_struct *stuff);

 int main(int argc, char **argv)
 {
    GtkApplication *app;
    int status;
    int i, j;

    struct main_struct stuff = {
 .da_filz=NULL
    };

    app=gtk_application_new("com.email.name.my.appname", G_APPLICATION_FLAGS_NONE);
    g_signal_connect(app, "activate", G_CALLBACK(app_activate), &stuff);
    status=g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);

    return(status);
  }/*End of main()****************************************/

/*Start of app_activate()***********************************/
  void app_activate(GtkApplication *app, struct main_struct *stuff)

  {
    GtkWidget *window=gtk_application_window_new(GTK_APPLICATION(app));
    gtk_window_set_title(GTK_WINDOW(window), "My App");
    gtk_window_set_default_size(GTK_WINDOW(window),
                  WINDOW_ISIZE, WINDOW_JSIZE);
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);
    stuff->window = window;

    GtkWidget *box1 = gtk_box_new(TRUE, 5);
    GtkAccelGroup *group = gtk_accel_group_new();
    GtkWidget *menubar = gtk_menu_bar_new();

    GtkWidget *da_filz = gtk_drawing_area_new();
    gtk_widget_set_size_request (da_filz, 800, 800);
    gtk_widget_set_hexpand(da_filz, TRUE);
    gtk_widget_set_vexpand(da_filz, TRUE);
    stuff->da_filz=da_filz;

    GtkWidget *swin_textview1_stuff = gtk_scrolled_window_new(NULL, NULL);
    gtk_widget_set_size_request (swin_textview1_stuff, 400, 300);
    gtk_widget_set_hexpand(swin_textview1_stuff, TRUE);
    gtk_widget_set_vexpand(swin_textview1_stuff, TRUE);
    /*gtk_container_add (GTK_CONTAINER (swin_textview1_stuff), stuff->textview1_stuff);*/

    GtkWidget *swin_filz_da_filz = gtk_scrolled_window_new (NULL, NULL);
    gtk_widget_set_size_request (swin_filz_da_filz, 300, 100);
    gtk_widget_set_hexpand(swin_filz_da_filz, TRUE);
    gtk_widget_set_vexpand(swin_filz_da_filz, TRUE);
    gtk_container_set_border_width (GTK_CONTAINER (swin_filz_da_filz), 5);
    gtk_container_add (GTK_CONTAINER (swin_filz_da_filz), da_filz);

    g_signal_connect(da_filz, "draw", G_CALLBACK(draw_filz), stuff);

    GtkWidget *grid_2=gtk_grid_new();

    GtkWidget *grid_filz=gtk_grid_new();
    GtkWidget *grid_filz_spins=gtk_grid_new();

    GtkWidget *swin_filz_spins = gtk_scrolled_window_new (NULL, NULL);
    gtk_widget_set_size_request (swin_filz_spins, 400, 300);
    gtk_widget_set_hexpand(swin_filz_spins, TRUE);
    gtk_widget_set_vexpand(swin_filz_spins, TRUE);

    gtk_container_set_border_width (GTK_CONTAINER (swin_filz_spins), 5);
    gtk_container_add (GTK_CONTAINER (swin_filz_spins), grid_filz_spins);

    gtk_grid_attach(GTK_GRID(grid_filz), swin_textview1_stuff, 0, 4, 5, 1);
    gtk_grid_attach(GTK_GRID(grid_filz), swin_filz_da_filz, 0, 8, 1, 1);

    GtkWidget *notebook = gtk_notebook_new();

    GtkWidget *label1 = gtk_label_new("label1");
    GtkWidget *label2 = gtk_label_new("label2");

    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), grid_filz, label1);
    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), grid_2, label2);

  gtk_box_pack_start (GTK_BOX(box1), menubar, FALSE, TRUE, 0);
  gtk_box_pack_start (GTK_BOX(box1), notebook, TRUE, TRUE, 0);
  gtk_container_add (GTK_CONTAINER (window), box1);
  gtk_window_add_accel_group(GTK_WINDOW(window), group);

    gtk_widget_show_all(window);

  }/*End of app_activate()**********************************************************/

    gboolean draw_filz (GtkWidget *da_filz, cairo_t *cr, struct main_struct *stuff)
    {
    GtkStyleContext *context;
    context = gtk_widget_get_style_context (da_filz);

    int x_length = gtk_widget_get_allocated_width (da_filz);
    int y_width_filz = gtk_widget_get_allocated_height (da_filz);

    /*gtk_render_background (context, cr, 0, 0, x_length, y_width_filz);
    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
    cairo_paint(cr);*/

    /*You will need to put a .png file into the working directory*/
    GdkPixbuf *image2 = gdk_pixbuf_new_from_file("mypixbuf.png", NULL);

    gdk_cairo_set_source_pixbuf(cr, image2, x_length, y_width_filz);
    gtk_render_background (context, cr, 0, 0, x_length, y_width_filz);
    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
    cairo_paint(cr);

    char str_sometext[20];
    sprintf(str_sometext, "Some text.");
    cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
    cairo_move_to(cr, 10, 10);
    cairo_show_text(cr, str_sometext);

    cairo_set_line_width(cr, 1.0);
    cairo_move_to(cr, 100, 100);
    cairo_line_to(cr, 253, 226);
    cairo_stroke(cr);

return FALSE;
}

Hi Roger @roger.matthews,
I have modified the following lines to make it work:

gtk_render_background (context, cr, 0, 0, x_length, y_width_filz);
cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
cairo_paint(cr);

/*You will need to put a .png file into the working directory*/
GdkPixbuf *image2 = gdk_pixbuf_new_from_file("mypixbuf.png", NULL);
gdk_cairo_set_source_pixbuf(cr, image2, 0.0, 0.0);
cairo_paint(cr);

The white background was applied upon the PNG. Now the background is applied first, and the PNG upon it.
I have also put 0.0, 0.0 in gdk_cairo_set_source_pixbuf(cr, image2, 0.0, 0.0);

|pixbuf_x|X coordinate of location to place upper left corner of pixbuf|
| — | — | — |
|pixbuf_y|Y coordinate of location to place upper left corner of pixbuf|

Hi Vincent,
have been away working for a couple of weeks so I’ve only now been able to have a look at your suggestions, and they have done the trick, thanks,
Roger

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.