原文: https://zetcode.com/gfx/cairo/compositing/

在 Cairo 图形编程教程的这一部分中,我们将定义合成操作。

合成是将来自不同来源的视觉元素组合成单个图像。 它们被用来创建一种幻觉,即所有这些元素都是同一场景的一部分。 合成在电影行业中被广泛使用来创造人群,否则将是昂贵或不可能创造的整个新世界。 (wikipedia.org)

工作方式

有几种合成操作。 Cairo 图形库具有 14 种不同的合成操作。

  1. #include <cairo.h>
  2. #include <gtk/gtk.h>
  3. void do_drawing(cairo_t *cr, gint x, gint w,
  4. gint h, cairo_operator_t op)
  5. {
  6. cairo_t *first_cr, *second_cr;
  7. cairo_surface_t *first, *second;
  8. first = cairo_surface_create_similar(cairo_get_target(cr),
  9. CAIRO_CONTENT_COLOR_ALPHA, w, h);
  10. second = cairo_surface_create_similar(cairo_get_target(cr),
  11. CAIRO_CONTENT_COLOR_ALPHA, w, h);
  12. first_cr = cairo_create(first);
  13. cairo_set_source_rgb(first_cr, 0, 0, 0.4);
  14. cairo_rectangle(first_cr, x, 20, 50, 50);
  15. cairo_fill(first_cr);
  16. second_cr = cairo_create(second);
  17. cairo_set_source_rgb(second_cr, 0.5, 0.5, 0);
  18. cairo_rectangle(second_cr, x+10, 40, 50, 50);
  19. cairo_fill(second_cr);
  20. cairo_set_operator(first_cr, op);
  21. cairo_set_source_surface(first_cr, second, 0, 0);
  22. cairo_paint(first_cr);
  23. cairo_set_source_surface(cr, first, 0, 0);
  24. cairo_paint(cr);
  25. cairo_surface_destroy(first);
  26. cairo_surface_destroy(second);
  27. cairo_destroy(first_cr);
  28. cairo_destroy(second_cr);
  29. }
  30. static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
  31. gpointer user_data)
  32. {
  33. cairo_operator_t oper[] = {
  34. CAIRO_OPERATOR_DEST_OVER,
  35. CAIRO_OPERATOR_DEST_IN,
  36. CAIRO_OPERATOR_OUT,
  37. CAIRO_OPERATOR_ADD,
  38. CAIRO_OPERATOR_ATOP,
  39. CAIRO_OPERATOR_DEST_ATOP,
  40. };
  41. GtkWidget *win = gtk_widget_get_toplevel(widget);
  42. gint width, height;
  43. gtk_window_get_size(GTK_WINDOW(win), &width, &height);
  44. gint i;
  45. gint x, y;
  46. for(x=20, y=20, i=0; i < 6; x+=80, i++) {
  47. do_drawing(cr, x, width, height, oper[i] );
  48. }
  49. return FALSE;
  50. }
  51. int main(int argc, char *argv[])
  52. {
  53. GtkWidget *window;
  54. GtkWidget *darea;
  55. gtk_init(&argc, &argv);
  56. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  57. darea = gtk_drawing_area_new();
  58. gtk_container_add(GTK_CONTAINER (window), darea);
  59. g_signal_connect(G_OBJECT(darea), "draw",
  60. G_CALLBACK(on_draw_event), NULL);
  61. g_signal_connect(window, "destroy",
  62. G_CALLBACK(gtk_main_quit), NULL);
  63. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  64. gtk_window_set_default_size(GTK_WINDOW(window), 510, 120);
  65. gtk_window_set_title(GTK_WINDOW(window), "Compositing operations");
  66. gtk_widget_show_all(window);
  67. gtk_main();
  68. return 0;
  69. }

在我们的示例中,我们将在两个正方形上显示 6 种不同的合成操作。

  1. first = cairo_surface_create_similar(cairo_get_target(cr),
  2. CAIRO_CONTENT_COLOR_ALPHA, w, h);
  3. second = cairo_surface_create_similar(cairo_get_target(cr),
  4. CAIRO_CONTENT_COLOR_ALPHA, w, h);

我们创建两个曲面。

  1. first_cr = cairo_create(first);
  2. cairo_set_source_rgb(first_cr, 0, 0, 0.4);
  3. cairo_rectangle(first_cr, x, 20, 50, 50);
  4. cairo_fill(first_cr);

我们在表面绘制一个矩形。

  1. cairo_set_operator(first_cr, op);
  2. cairo_set_source_surface(first_cr, second, 0, 0);
  3. cairo_paint(first_cr);

我们在曲面上应用合成操作。

  1. cairo_set_source_surface(cr, first, 0, 0);
  2. cairo_paint(cr);

最后,我们将结果绘制到 GTK+ 窗口上。

  1. cairo_operator_t oper[] = {
  2. CAIRO_OPERATOR_DEST_OVER,
  3. CAIRO_OPERATOR_DEST_IN,
  4. CAIRO_OPERATOR_OUT,
  5. CAIRO_OPERATOR_ADD,
  6. CAIRO_OPERATOR_ATOP,
  7. CAIRO_OPERATOR_DEST_ATOP,
  8. };

在我们的示例中,我们使用这六个合成操作。

合成 - 图1

图:合成操作

本章介绍了 Cairo 合成。