Cairo FAQ Shapes and fills

Материал из Wiki.crossplatform.ru

(Различия между версиями)
Перейти к: навигация, поиск
(Новая: In this part of the Cairo tutorial, we will create some basic and more advanced shapes. We will fill them with solid colors, patterns and gradients. == Basic shapes == The Cairo API h...)
(Удалено по требованию автора...)
 
Строка 1: Строка 1:
-
In this part of the Cairo tutorial, we will create some basic and more advanced shapes. We will fill them with solid colors, patterns and gradients.
 
-
== Basic shapes ==
 
-
 
-
The Cairo API has several functions to create some basic shapes.
 
-
 
-
<source lang="cpp">
 
-
#include <cairo.h>
 
-
#include <gtk/gtk.h>
 
-
#include <math.h>
 
-
 
-
 
-
static gboolean
 
-
on_expose_event(GtkWidget *widget,
 
-
    GdkEventExpose *event,
 
-
    gpointer data)
 
-
{
 
-
  cairo_t *cr;
 
-
 
-
  cr = gdk_cairo_create (widget->window);
 
-
 
-
  cairo_set_source_rgb(cr, 0, 0, 0);
 
-
  cairo_set_line_width(cr, 1);
 
-
 
-
  cairo_rectangle(cr, 20, 20, 120, 80);
 
-
  cairo_rectangle(cr, 180, 20, 80, 80);
 
-
  cairo_stroke_preserve(cr);
 
-
  cairo_set_source_rgb(cr, 1, 1, 1);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_set_source_rgb(cr, 0, 0, 0);
 
-
  cairo_arc(cr, 330, 60, 40, 0, 2*M_PI);
 
-
  cairo_stroke_preserve(cr);
 
-
  cairo_set_source_rgb(cr, 1, 1, 1);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_set_source_rgb(cr, 0, 0, 0);
 
-
  cairo_arc(cr, 90, 160, 40, M_PI/4, M_PI);
 
-
  cairo_close_path(cr);
 
-
  cairo_stroke_preserve(cr);
 
-
  cairo_set_source_rgb(cr, 1, 1, 1);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_set_source_rgb(cr, 0, 0, 0);
 
-
  cairo_translate(cr, 220, 180);
 
-
  cairo_scale(cr, 1, 0.7);
 
-
  cairo_arc(cr, 0, 0, 50, 0, 2*M_PI);
 
-
  cairo_stroke_preserve(cr);
 
-
  cairo_set_source_rgb(cr, 1, 1, 1);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_destroy(cr);
 
-
 
-
  return FALSE;
 
-
}
 
-
 
-
 
-
int
 
-
main (int argc, char *argv[])
 
-
{
 
-
 
-
  GtkWidget *window;
 
-
  GtkWidget *darea; 
 
-
 
-
  gtk_init(&argc, &argv);
 
-
 
-
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
-
 
-
  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(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), 390, 240);
 
-
 
-
  gtk_widget_show_all(window);
 
-
 
-
  gtk_main();
 
-
 
-
  return 0;
 
-
}
 
-
 
-
</source>
 
-
 
-
In this example, we will create a rectangle, a square, a circle, an arc and an ellipse.
 
-
 
-
<source lang="cpp">
 
-
cairo_rectangle(cr, 20, 20, 120, 80);
 
-
cairo_rectangle(cr, 180, 20, 80, 80);
 
-
</source>
 
-
 
-
The <b>cairo_rectangle()</b> is used to create both squares and rectangles. A square is just a  specific type of a rectangle.
 
-
 
-
<source lang="cpp">
 
-
cairo_arc(cr, 330, 60, 40, 0, 2*M_PI);
 
-
</source>
 
-
 
-
This line creates a circle.
 
-
 
-
<source lang="cpp">
 
-
cairo_scale(cr, 1, 0.7);
 
-
cairo_arc(cr, 0, 0, 50, 0, 2*M_PI);
 
-
</source>
 
-
 
-
We use the <b>cairo_scale()</b> function call to create an ellipse.
 
-
 
-
[[image: cairo_faq_shapes.png | center]]
 
-
 
-
Other shapes can be created using a combination of basic primitives.
 
-
 
-
<source lang="cpp">
 
-
#include <cairo.h>
 
-
#include <gtk/gtk.h>
 
-
 
-
 
-
int points[11][2] = {
 
-
    { 0, 85 },
 
-
    { 75, 75 },
 
-
    { 100, 10 },
 
-
    { 125, 75 },
 
-
    { 200, 85 },
 
-
    { 150, 125 },
 
-
    { 160, 190 },
 
-
    { 100, 150 },
 
-
    { 40, 190 },
 
-
    { 50, 125 },
 
-
    { 0, 85 }
 
-
};
 
-
 
-
static gboolean
 
-
on_expose_event(GtkWidget *widget,
 
-
    GdkEventExpose *event,
 
-
    gpointer data)
 
-
{
 
-
  cairo_t *cr;
 
-
 
-
  cr = gdk_cairo_create (widget->window);
 
-
 
-
  cairo_set_source_rgb(cr, 0, 0, 0);
 
-
  cairo_set_line_width(cr, 1);
 
-
 
-
 
-
  gint i;
 
-
  for ( i = 0; i < 10; i++ ) {
 
-
      cairo_line_to(cr, points[i][0], points[i][1]);
 
-
  }
 
-
 
-
  cairo_close_path(cr);
 
-
  cairo_stroke_preserve(cr);
 
-
  cairo_set_source_rgb(cr, 1, 1, 1);
 
-
  cairo_fill(cr);
 
-
 
-
 
-
  cairo_move_to(cr, 240, 40);
 
-
  cairo_line_to(cr, 240, 160);
 
-
  cairo_line_to(cr, 350, 160);
 
-
  cairo_close_path(cr);
 
-
 
-
  cairo_set_source_rgb(cr, 0, 0, 0);
 
-
  cairo_stroke_preserve(cr);
 
-
  cairo_set_source_rgb(cr, 1, 1, 1);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_move_to(cr, 380, 40);
 
-
  cairo_line_to(cr, 380, 160);
 
-
  cairo_line_to(cr, 450, 160);
 
-
  cairo_curve_to(cr, 440, 155, 380, 145, 380, 40);
 
-
 
-
  cairo_set_source_rgb(cr, 0, 0, 0);
 
-
  cairo_stroke_preserve(cr);
 
-
  cairo_set_source_rgb(cr, 1, 1, 1);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_destroy(cr);
 
-
 
-
  return FALSE;
 
-
}
 
-
 
-
 
-
int
 
-
main (int argc, char *argv[])
 
-
{
 
-
 
-
  GtkWidget *window;
 
-
  GtkWidget *darea;
 
-
 
-
  gtk_init(&argc, &argv);
 
-
 
-
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
-
 
-
  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(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), 460, 240);
 
-
 
-
  gtk_widget_show_all(window);
 
-
 
-
  gtk_main();
 
-
 
-
  return 0;
 
-
}
 
-
</source>
 
-
 
-
In this example, we create a star object a triangle and a modified triangle. These objects are created using lines  and one curve.
 
-
 
-
<source lang="cpp">
 
-
gint i;
 
-
for ( i = 0; i < 10; i++ ) {
 
-
    cairo_line_to(cr, points[i][0], points[i][1]);
 
-
}
 
-
 
-
cairo_close_path(cr);
 
-
</source>
 
-
 
-
The star is drawn by joining all the points that are in the points array. The star is finished by calling the <b>cairo_close_path()</b> function, which joins the last two points of a star.
 
-
 
-
<source lang="cpp">
 
-
cairo_move_to(cr, 380, 40);
 
-
cairo_line_to(cr, 380, 160);
 
-
cairo_line_to(cr, 450, 160);
 
-
cairo_curve_to(cr, 440, 155, 380, 145, 380, 40);
 
-
</source>
 
-
 
-
The modified rectangle is a simple combination of two lines and one curve.
 
-
 
-
[[image: cairo_faq_shapes2.png | center]]
 
-
 
-
== Fills ==
 
-
 
-
Fills fill the interiors of shapes. Fills can be solid colors, patters or gradients.
 
-
 
-
=== Solid colors ===
 
-
 
-
A color is an object representing a combination of Red, Green, and Blue (RGB) intensity values. Cairo valid RGB values are in the range 0 to 1.
 
-
 
-
<source lang="cpp">
 
-
 
-
#include <cairo.h>
 
-
#include <gtk/gtk.h>
 
-
 
-
 
-
static gboolean
 
-
on_expose_event(GtkWidget *widget,
 
-
    GdkEventExpose *event,
 
-
    gpointer data)
 
-
{
 
-
  cairo_t *cr;
 
-
 
-
  cr = gdk_cairo_create(widget->window);
 
-
 
-
  int width, height;
 
-
  gtk_window_get_size(GTK_WINDOW(widget), &width, &height); 
 
-
 
-
 
-
  cairo_set_source_rgb(cr, 0.5, 0.5, 1);
 
-
  cairo_rectangle(cr, 20, 20, 100, 100);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
 
-
  cairo_rectangle(cr, 150, 20, 100, 100);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_set_source_rgb(cr, 0, 0.3, 0);
 
-
  cairo_rectangle(cr, 20, 140, 100, 100);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_set_source_rgb(cr, 1, 0, 0.5);
 
-
  cairo_rectangle(cr, 150, 140, 100, 100);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_destroy(cr);
 
-
 
-
  return FALSE;
 
-
}
 
-
 
-
 
-
int
 
-
main (int argc, char *argv[])
 
-
{
 
-
  GtkWidget *window;
 
-
 
-
  gtk_init(&argc, &argv);
 
-
 
-
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
-
 
-
  g_signal_connect(G_OBJECT(window), "expose-event",
 
-
      G_CALLBACK(on_expose_event), NULL);
 
-
  g_signal_connect(G_OBJECT(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), 270, 260);
 
-
  gtk_window_set_title(GTK_WINDOW(window), "colors");
 
-
 
-
  gtk_widget_set_app_paintable(window, TRUE);
 
-
  gtk_widget_show_all(window);
 
-
 
-
  gtk_main();
 
-
 
-
  return 0;
 
-
}
 
-
</source>
 
-
 
-
In the example we draw four colored rectangles
 
-
 
-
 
-
<source lang="cpp">
 
-
cairo_set_source_rgb(cr, 0.5, 0.5, 1);
 
-
cairo_rectangle(cr, 20, 20, 100, 100);
 
-
cairo_fill(cr);
 
-
</source>
 
-
 
-
The <b>cairo_set_source_rgb()</b> function call sets the source to an opaque color. The parameters are the Red, Green, Blue intensity values. The source is used to fill the interior of a rectangle by calling the <b>cairo_fill()</b> function.
 
-
 
-
[[image: cairo_faq_colors.png | center]]
 
-
 
-
=== Patterns ===
 
-
 
-
Patterns are complex graphical objects that can fill the shapes.
 
-
 
-
<source lang="cpp">
 
-
#include <cairo.h>
 
-
 
-
#include <gtk/gtk.h>
 
-
 
-
cairo_surface_t *surface1;
 
-
cairo_surface_t *surface2;
 
-
cairo_surface_t *surface3;
 
-
cairo_surface_t *surface4;
 
-
 
-
static void create_surfaces() {
 
-
  surface1 = cairo_image_surface_create_from_png("blueweb.png");
 
-
  surface2 = cairo_image_surface_create_from_png("maple.png");
 
-
  surface3 = cairo_image_surface_create_from_png("crack.png");
 
-
  surface4 = cairo_image_surface_create_from_png("chocolate.png");
 
-
}
 
-
 
-
static void destroy_surfaces() {
 
-
  g_print("destroying surfaces");
 
-
  cairo_surface_destroy(surface1);
 
-
  cairo_surface_destroy(surface2);
 
-
  cairo_surface_destroy(surface3);
 
-
  cairo_surface_destroy(surface4);
 
-
}
 
-
 
-
 
-
static gboolean
 
-
on_expose_event(GtkWidget *widget,
 
-
    GdkEventExpose *event,
 
-
    gpointer data)
 
-
{
 
-
  cairo_t *cr;
 
-
 
-
  cairo_pattern_t *pattern1;
 
-
  cairo_pattern_t *pattern2;
 
-
  cairo_pattern_t *pattern3;
 
-
  cairo_pattern_t *pattern4;
 
-
 
-
  cr = gdk_cairo_create(widget->window);
 
-
 
-
  int width, height;
 
-
  gtk_window_get_size(GTK_WINDOW(widget), &width, &height); 
 
-
 
-
 
-
  pattern1 = cairo_pattern_create_for_surface(surface1);
 
-
  pattern2 = cairo_pattern_create_for_surface(surface2);
 
-
  pattern3 = cairo_pattern_create_for_surface(surface3);
 
-
  pattern4 = cairo_pattern_create_for_surface(surface4);
 
-
 
-
 
-
  cairo_set_source(cr, pattern1);
 
-
  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
 
-
  cairo_rectangle(cr, 20, 20, 100, 100);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_set_source(cr, pattern2);
 
-
  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
 
-
  cairo_rectangle(cr, 150, 20, 100, 100);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_set_source(cr, pattern3);
 
-
  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
 
-
  cairo_rectangle(cr, 20, 140, 100, 100);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_set_source(cr, pattern4);
 
-
  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
 
-
  cairo_rectangle(cr, 150, 140, 100, 100);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_pattern_destroy(pattern1);
 
-
  cairo_pattern_destroy(pattern2);
 
-
  cairo_pattern_destroy(pattern3);
 
-
  cairo_pattern_destroy(pattern4);
 
-
 
-
  cairo_destroy(cr);
 
-
 
-
  return FALSE;
 
-
}
 
-
 
-
 
-
int
 
-
main (int argc, char *argv[])
 
-
{
 
-
  GtkWidget *window;
 
-
 
-
  gtk_init(&argc, &argv);
 
-
 
-
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
-
 
-
  g_signal_connect(G_OBJECT(window), "expose-event",
 
-
      G_CALLBACK(on_expose_event), NULL);
 
-
  g_signal_connect(G_OBJECT(window), "destroy",
 
-
      G_CALLBACK(gtk_main_quit), NULL);
 
-
 
-
  create_surfaces();
 
-
 
-
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
 
-
  gtk_window_set_default_size(GTK_WINDOW(window), 270, 260);
 
-
  gtk_window_set_title(GTK_WINDOW(window), "patterns");
 
-
 
-
  gtk_widget_set_app_paintable(window, TRUE);
 
-
  gtk_widget_show_all(window);
 
-
 
-
  gtk_main();
 
-
 
-
  destroy_surfaces();
 
-
 
-
  return 0;
 
-
}
 
-
 
-
</source>
 
-
 
-
In this example we draw four rectangles again. This time, we fill them with some patterns.
 
-
We use four pattern images from the <b>Gimp</b> image manipulation program. We must retain the original size of those patterns, because we are going to tile them.
 
-
 
-
We create image surfaces outside the <b>on_expose_event()</b> function. It would not be efficient to read from harddisk each time, the window needs to be redrawn.
 
-
 
-
<source lang="cpp">
 
-
pattern1 = cairo_pattern_create_for_surface(surface1);
 
-
</source>
 
-
 
-
We create a pattern from the surface by calling the <b>cairo_pattern_create_for_surface()</b> function.
 
-
 
-
<source lang="cpp">
 
-
  cairo_set_source(cr, pattern1);
 
-
  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
 
-
  cairo_rectangle(cr, 20, 20, 100, 100);
 
-
  cairo_fill(cr);
 
-
</source>
 
-
 
-
Here we draw our first rectangle. The <b>cairo_rectangle()</b> creates a rectangular path.
 
-
Finally, <b>cairo_fill()</b> fills the path with the source.
 
-
 
-
[[image: cairo_faq_patterns.png | center]]
 
-
 
-
=== Gradients ===
 
-
 
-
In computer graphics, gradient is a smooth blending of shades from light to dark or from one color to another. In 2D drawing programs and paint programs, gradients are used to create colorful backgrounds and special effects as well as to simulate lights and shadows. (answers.com)
 
-
 
-
<source lang="cpp">
 
-
 
-
#include <cairo.h>
 
-
#include <gtk/gtk.h>
 
-
 
-
static gboolean
 
-
on_expose_event(GtkWidget *widget,
 
-
    GdkEventExpose *event,
 
-
    gpointer data)
 
-
{
 
-
  cairo_t *cr;
 
-
  cairo_pattern_t *pat1;
 
-
  cairo_pattern_t *pat2;
 
-
  cairo_pattern_t *pat3;
 
-
 
-
  cr = gdk_cairo_create(widget->window);
 
-
 
-
  pat1 = cairo_pattern_create_linear(0.0, 0.0,  350.0, 350.0);
 
-
 
-
  gdouble j;
 
-
  gint count = 1;
 
-
  for ( j = 0.1; j < 1; j += 0.1 ) {
 
-
      if (( count % 2 ))  {
 
-
          cairo_pattern_add_color_stop_rgb(pat1, j, 0, 0, 0);
 
-
      } else {
 
-
          cairo_pattern_add_color_stop_rgb(pat1, j, 1, 0, 0);
 
-
      }
 
-
  count++;
 
-
  }
 
-
 
-
  cairo_rectangle(cr, 20, 20, 300, 100);
 
-
  cairo_set_source(cr, pat1);
 
-
  cairo_fill(cr);
 
-
 
-
 
-
  pat2 = cairo_pattern_create_linear(0.0, 0.0,  350.0, 0.0);
 
-
 
-
  gdouble i;
 
-
  count = 1;
 
-
  for ( i = 0.05; i < 0.95; i += 0.025 ) {
 
-
      if (( count % 2 ))  {
 
-
          cairo_pattern_add_color_stop_rgb(pat2, i, 0, 0, 0);
 
-
      } else {
 
-
          cairo_pattern_add_color_stop_rgb(pat2, i, 0, 0, 1);
 
-
      }
 
-
  count++;
 
-
  }
 
-
 
-
  cairo_rectangle(cr, 20, 140, 300, 100);
 
-
  cairo_set_source(cr, pat2);
 
-
  cairo_fill(cr);
 
-
 
-
 
-
  pat3 = cairo_pattern_create_linear(20.0, 260.0, 20.0, 360.0);
 
-
 
-
  cairo_pattern_add_color_stop_rgb(pat3, 0.1, 0, 0, 0);
 
-
  cairo_pattern_add_color_stop_rgb(pat3, 0.5, 1, 1, 0);
 
-
  cairo_pattern_add_color_stop_rgb(pat3, 0.9, 0, 0, 0);
 
-
 
-
  cairo_rectangle(cr, 20, 260, 300, 100);
 
-
  cairo_set_source(cr, pat3);
 
-
  cairo_fill(cr);
 
-
 
-
  cairo_pattern_destroy(pat1);
 
-
  cairo_pattern_destroy(pat2);
 
-
  cairo_pattern_destroy(pat3);
 
-
 
-
  cairo_destroy(cr);
 
-
 
-
  return FALSE;
 
-
}
 
-
 
-
 
-
int
 
-
main (int argc, char *argv[])
 
-
{
 
-
  GtkWidget *window;
 
-
 
-
  gtk_init(&argc, &argv);
 
-
 
-
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
-
 
-
  g_signal_connect(G_OBJECT(window), "expose-event",
 
-
      G_CALLBACK(on_expose_event), NULL);
 
-
  g_signal_connect(G_OBJECT(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), 340, 390);
 
-
  gtk_window_set_title(GTK_WINDOW(window), "gradients");
 
-
 
-
  gtk_widget_set_app_paintable(window, TRUE);
 
-
  gtk_widget_show_all(window);
 
-
 
-
  gtk_main();
 
-
 
-
  return 0;
 
-
}
 
-
</source>
 
-
 
-
In our example, we draw three rectangles with three different gradients.
 
-
 
-
<source lang="cpp">
 
-
pat3 = cairo_pattern_create_linear(20.0, 260.0, 20.0, 360.0);
 
-
</source>
 
-
 
-
Here we create a linear gradient pattern. The parameters specify the line, along which we draw the gradient. In our case it is a vertical line.
 
-
 
-
<source lang="cpp">
 
-
cairo_pattern_add_color_stop_rgb(pat3, 0.1, 0, 0, 0);
 
-
cairo_pattern_add_color_stop_rgb(pat3, 0.5, 1, 1, 0);
 
-
cairo_pattern_add_color_stop_rgb(pat3, 0.9, 0, 0, 0);
 
-
</source>
 
-
 
-
We define color stops to produce our gradient pattern. In this case, the gradient is a blending of black and yellow colors. By adding two black and one yellow stops, we create a horizontal gradient pattern.
 
-
What these stops actually mean? In our case, we begin with black color, which will stop at 1/10 of the size. Then we begin to gradually paint in yellow, which will culminate at the centre of the shape. The yellow color stops at 9/10 of the  size, where we begin painting in black again, until the end.
 
-
 
-
[[image: cairo_faq_gradients.png | center]]
 
-
 
-
[[Категория:GTK+]]
 
-
[[Категория:Cairo]]
 

Текущая версия на 11:30, 7 апреля 2009