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

在 Cairo 图形教程的这一部分中,我们将介绍渐变。 我们将提到线性和径向渐变。

在计算机图形学中,渐变是从浅到深或从一种颜色到另一种颜色的阴影的平滑混合。 在 2D 绘图程序和绘画程序中,渐变用于创建彩色背景和特殊效果以及模拟灯光和阴影。 (answers.com)

线性渐变

线性渐变是沿着一条线的颜色混合或颜色阴影混合。 它们是使用cairo_pattern_create_linear()函数创建的。

  1. #include <cairo.h>
  2. #include <gtk/gtk.h>
  3. void draw_gradient1(cairo_t *);
  4. void draw_gradient2(cairo_t *);
  5. void draw_gradient3(cairo_t *);
  6. static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
  7. gpointer user_data)
  8. {
  9. draw_gradient1(cr);
  10. draw_gradient2(cr);
  11. draw_gradient3(cr);
  12. return FALSE;
  13. }
  14. void draw_gradient1(cairo_t *cr)
  15. {
  16. cairo_pattern_t *pat1;
  17. pat1 = cairo_pattern_create_linear(0.0, 0.0, 350.0, 350.0);
  18. gdouble j;
  19. gint count = 1;
  20. for ( j = 0.1; j < 1; j += 0.1 ) {
  21. if (( count % 2 )) {
  22. cairo_pattern_add_color_stop_rgb(pat1, j, 0, 0, 0);
  23. } else {
  24. cairo_pattern_add_color_stop_rgb(pat1, j, 1, 0, 0);
  25. }
  26. count++;
  27. }
  28. cairo_rectangle(cr, 20, 20, 300, 100);
  29. cairo_set_source(cr, pat1);
  30. cairo_fill(cr);
  31. cairo_pattern_destroy(pat1);
  32. }
  33. void draw_gradient2(cairo_t *cr)
  34. {
  35. cairo_pattern_t *pat2;
  36. pat2 = cairo_pattern_create_linear(0.0, 0.0, 350.0, 0.0);
  37. gdouble i;
  38. gint count = 1;
  39. for ( i = 0.05; i < 0.95; i += 0.025 ) {
  40. if (( count % 2 )) {
  41. cairo_pattern_add_color_stop_rgb(pat2, i, 0, 0, 0);
  42. } else {
  43. cairo_pattern_add_color_stop_rgb(pat2, i, 0, 0, 1);
  44. }
  45. count++;
  46. }
  47. cairo_rectangle(cr, 20, 140, 300, 100);
  48. cairo_set_source(cr, pat2);
  49. cairo_fill(cr);
  50. cairo_pattern_destroy(pat2);
  51. }
  52. void draw_gradient3(cairo_t *cr)
  53. {
  54. cairo_pattern_t *pat3;
  55. pat3 = cairo_pattern_create_linear(20.0, 260.0, 20.0, 360.0);
  56. cairo_pattern_add_color_stop_rgb(pat3, 0.1, 0, 0, 0);
  57. cairo_pattern_add_color_stop_rgb(pat3, 0.5, 1, 1, 0);
  58. cairo_pattern_add_color_stop_rgb(pat3, 0.9, 0, 0, 0);
  59. cairo_rectangle(cr, 20, 260, 300, 100);
  60. cairo_set_source(cr, pat3);
  61. cairo_fill(cr);
  62. cairo_pattern_destroy(pat3);
  63. }
  64. int main(int argc, char *argv[])
  65. {
  66. GtkWidget *window;
  67. GtkWidget *darea;
  68. gtk_init(&argc, &argv);
  69. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  70. darea = gtk_drawing_area_new();
  71. gtk_container_add(GTK_CONTAINER (window), darea);
  72. g_signal_connect(G_OBJECT(darea), "draw",
  73. G_CALLBACK(on_draw_event), NULL);
  74. g_signal_connect(G_OBJECT(window), "destroy",
  75. G_CALLBACK(gtk_main_quit), NULL);
  76. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  77. gtk_window_set_default_size(GTK_WINDOW(window), 340, 390);
  78. gtk_window_set_title(GTK_WINDOW(window), "Linear gradients");
  79. gtk_widget_set_app_paintable(window, TRUE);
  80. gtk_widget_show_all(window);
  81. gtk_main();
  82. return 0;
  83. }

该示例绘制了三个填充有线性渐变的矩形。

  1. pat3 = cairo_pattern_create_linear(20.0, 260.0, 20.0, 360.0);

在这里,我们创建一个线性渐变图案。 参数指定直线,沿着该直线绘制渐变。 在我们的情况下,这是一条垂直线。

  1. cairo_pattern_add_color_stop_rgb(pat3, 0.1, 0, 0, 0);
  2. cairo_pattern_add_color_stop_rgb(pat3, 0.5, 1, 1, 0);
  3. cairo_pattern_add_color_stop_rgb(pat3, 0.9, 0, 0, 0);

我们定义色标以产生渐变图案。 在这种情况下,渐变是黑色和黄色的混合。 通过添加两个黑色和一个黄色色标,我们创建了一个水平渐变图案。 这些停止实际上是什么意思? 在我们的情况下,我们从黑色开始,该颜色将以大小的 1/10 停止。 然后,我们开始逐渐涂成黄色,最终达到形状的中心。 黄色停在大小的 9/10,我们再次开始用黑色绘画,直到结束。

渐变 - 图1

图:线性渐变

径向渐变

径向渐变是两个圆之间颜色或阴影的混合。 cairo_pattern_create_radial()函数用于在 Cairo 创建径向渐变。

  1. #include <cairo.h>
  2. #include <math.h>
  3. #include <gtk/gtk.h>
  4. void draw_gradient1(cairo_t *);
  5. void draw_gradient2(cairo_t *);
  6. static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
  7. gpointer user_data)
  8. {
  9. draw_gradient1(cr);
  10. draw_gradient2(cr);
  11. return FALSE;
  12. }
  13. void draw_gradient1(cairo_t *cr)
  14. {
  15. cairo_pattern_t *r1;
  16. cairo_set_source_rgba(cr, 0, 0, 0, 1);
  17. cairo_set_line_width(cr, 12);
  18. cairo_translate(cr, 60, 60);
  19. r1 = cairo_pattern_create_radial(30, 30, 10, 30, 30, 90);
  20. cairo_pattern_add_color_stop_rgba(r1, 0, 1, 1, 1, 1);
  21. cairo_pattern_add_color_stop_rgba(r1, 1, 0.6, 0.6, 0.6, 1);
  22. cairo_set_source(cr, r1);
  23. cairo_arc(cr, 0, 0, 40, 0, M_PI * 2);
  24. cairo_fill(cr);
  25. cairo_pattern_destroy(r1);
  26. }
  27. void draw_gradient2(cairo_t *cr)
  28. {
  29. cairo_pattern_t *r2;
  30. cairo_translate(cr, 120, 0);
  31. r2 = cairo_pattern_create_radial(0, 0, 10, 0, 0, 40);
  32. cairo_pattern_add_color_stop_rgb(r2, 0, 1, 1, 0);
  33. cairo_pattern_add_color_stop_rgb(r2, 0.8, 0, 0, 0);
  34. cairo_set_source(cr, r2);
  35. cairo_arc(cr, 0, 0, 40, 0, M_PI * 2);
  36. cairo_fill(cr);
  37. }
  38. int main(int argc, char *argv[])
  39. {
  40. GtkWidget *window;
  41. GtkWidget *darea;
  42. gtk_init(&argc, &argv);
  43. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  44. darea = gtk_drawing_area_new();
  45. gtk_container_add(GTK_CONTAINER (window), darea);
  46. g_signal_connect(G_OBJECT(darea), "draw",
  47. G_CALLBACK(on_draw_event), NULL);
  48. g_signal_connect(G_OBJECT(window), "destroy",
  49. G_CALLBACK(gtk_main_quit), NULL);
  50. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  51. gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
  52. gtk_window_set_title(GTK_WINDOW(window), "Radial gradients");
  53. gtk_widget_set_app_paintable(window, TRUE);
  54. gtk_widget_show_all(window);
  55. gtk_main();
  56. return 0;
  57. }

在示例中,我们绘制了两个径向渐变。

  1. r1 = cairo_pattern_create_radial(30, 30, 10, 30, 30, 90);
  2. cairo_pattern_add_color_stop_rgba(r1, 0, 1, 1, 1, 1);
  3. cairo_pattern_add_color_stop_rgba(r1, 1, 0.6, 0.6, 0.6, 1);
  4. cairo_set_source(cr, r1);
  5. cairo_arc(cr, 0, 0, 40, 0, M_PI * 2);
  6. cairo_fill(cr);

我们画一个圆,并用径向渐变填充其内部。 径向梯度由两个圆定义。 cairo_pattern_add_color_stop_rgba()函数定义颜色。 我们可以试验圆的位置或半径的长度。 在第一个渐变示例中,我们创建了一个类似于 3D 形状的对象。

  1. r2 = cairo_pattern_create_radial(0, 0, 10, 0, 0, 40);
  2. cairo_pattern_add_color_stop_rgb(r2, 0, 1, 1, 0);
  3. cairo_pattern_add_color_stop_rgb(r2, 0.8, 0, 0, 0);
  4. cairo_set_source(cr, r2);
  5. cairo_arc(cr, 0, 0, 40, 0, M_PI * 2);
  6. cairo_fill(cr);

在此示例中,定义径向渐变的圆和自定义绘制的圆具有共同的中心点。

渐变 - 图2

图:径向渐变

在 Cairo 图形教程的这一章中,我们介绍了渐变。