7. Compositing

In this part of the Cairo graphics programming tutorial, we will define compositing operations

Operations

There are several compositing operations.

The cairo graphics library has 14 different compositing operations.

compositing.c

  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
#include <cairo.h>
#include <gtk/gtk.h>

static void draw(cairo_t *cr, gint x, gint w, gint h, cairo_operator_t op);
static gboolean on_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data);

int main(int argc, char *argv[]){
  GtkWidget *window;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  g_signal_connect(window, "expose-event", G_CALLBACK(on_expose_event), NULL);
  g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 510, 120);
  
  gtk_window_set_title(GTK_WINDOW(window), "compositing operations");

  gtk_widget_set_app_paintable(window, TRUE);
  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

static void draw(cairo_t *cr, gint x, gint w, gint h, cairo_operator_t op){
  cairo_t *first_cr, *second_cr;
  cairo_surface_t *first, *second;

  /*
    we create two surfaces
  */
  first = cairo_surface_create_similar(cairo_get_target(cr), CAIRO_CONTENT_COLOR_ALPHA, w, h);
  second = cairo_surface_create_similar(cairo_get_target(cr), CAIRO_CONTENT_COLOR_ALPHA, w, h);

  /* we draw a rectangle into the surface */
  first_cr = cairo_create(first);
  cairo_set_source_rgb(first_cr, 0, 0, 0.4);
  cairo_rectangle(first_cr, x, 20, 50, 50);
  cairo_fill(first_cr);

  second_cr = cairo_create(second);
  cairo_set_source_rgb(second_cr, 0.5, 0.5, 0);
  cairo_rectangle(second_cr, x+10, 40, 50, 50);
  cairo_fill(second_cr);

  /*
    we apply the compositing operation on the surfaces
  */
  cairo_set_operator(first_cr, op);
  cairo_set_source_surface(first_cr, second, 0, 0);
  cairo_paint(first_cr);

  /*
    finally we draw the outcome onto the GTK+ window
  */
  cairo_set_source_surface(cr, first, 0, 0);
  cairo_paint(cr);

  cairo_surface_destroy(first);
  cairo_surface_destroy(second);

  cairo_destroy(first_cr);
  cairo_destroy(second_cr);
}

static gboolean on_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data){
  cairo_t *cr;

  gint w, h;
  gint x, y;

  /*
    in our example, we use these six compositing operations.
  */
  cairo_operator_t oper[] = {
    CAIRO_OPERATOR_DEST_OVER,
    CAIRO_OPERATOR_DEST_IN,
    CAIRO_OPERATOR_OUT,
    CAIRO_OPERATOR_ADD,
    CAIRO_OPERATOR_ATOP,
    CAIRO_OPERATOR_DEST_ATOP
  };

  gtk_window_get_size(GTK_WINDOW(widget), &w, &h);

  cr = gdk_cairo_create(widget->window);

  gint i;
  for(x = 20, y= 20, i = 0; i < 6; x += 80, i++){
    draw(cr, x, w, h, oper[i]);
  }

  cairo_destroy(cr);

  return FALSE;
}

compositing.c の実行結果は:

_images/compositing.png

Table Of Contents

Previous topic

6. Transparency

Next topic

8. Clipping and Masking