The Cairo graphics tutorial -------Shapes and fills in Cairo

转载 2012年03月30日 08:18:45

In this part of the Cairo tutorial, we will create some basic and more advanced shapes. We will fill them withsolid colors, patterns and gradients.


Basic shapes

The Cairo API has several functions to create some basic shapes.

#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;
}

In this example, we will create a rectangle, a square, a circle, an arc and an ellipse.

 cairo_rectangle(cr, 20, 20, 120, 80);
 cairo_rectangle(cr, 180, 20, 80, 80);

The cairo_rectangle() is used to create both squares and rectangles. A square is just a specific type of a rectangle.

 cairo_arc(cr, 330, 60, 40, 0, 2*M_PI);

This line creates a circle.

 cairo_scale(cr, 1, 0.7);
 cairo_arc(cr, 0, 0, 50, 0, 2*M_PI);

We use the cairo_scale() function call to create an ellipse.


Shapes
Figure: Shapes

Other shapes can be created using a combination of basic primitives.


#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;
}

In this example, we create a star object a triangle and a modified triangle. These objects are created using lines and one curve.

 gint i;
 for ( i = 0; i < 10; i++ ) {
     cairo_line_to(cr, points[i][0], points[i][1]);
 }

 cairo_close_path(cr);

The star is drawn by joining all the points that are in the points array. The star is finished by calling the cairo_close_path() function, which joins the last two points of a star.

 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);

The modified rectangle is a simple combination of two lines and one curve.


Shapes
Figure: Shapes

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.

#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;
}

In the example we draw four colored rectangles

 cairo_set_source_rgb(cr, 0.5, 0.5, 1);
 cairo_rectangle(cr, 20, 20, 100, 100);
 cairo_fill(cr);

The cairo_set_source_rgb() 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 cairo_fill() function.


Solid colors
Figure: Solid Colors

Patterns

Patterns are complex graphical objects that can fill the shapes.

#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;
}

In this example we draw four rectangles again. This time, we fill them with some patterns. We use four pattern images from the Gimp 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 on_expose_event() function. It would not be efficient to read from harddisk each time, the window needs to be redrawn.

 pattern1 = cairo_pattern_create_for_surface(surface1);

We create a pattern from the surface by calling the cairo_pattern_create_for_surface() function.

  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);

Here we draw our first rectangle. The cairo_set_source() tells the Cairo context to use a pattern as a source for drawing. The image patterns may not fit exactly the shape. We set the mode to CAIRO_EXTEND_REPEAT, which causes the pattern to be tiled by repeating. The cairo_rectangle() creates a rectangular path.Finally, cairo_fill() fills the path with the source.


Patterns
Figure: Patterns

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)

#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;
}

In our example, we draw three rectangles with three different gradients.

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

Here we create a linear gradient pattern. The parameters specify the line, along which we draw thegradient. In our case it is a vertical line.

 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);

We define color stops to produce our gradient pattern. In this case, the gradient is a blending of black and yellowcolors. 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 beginto 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.


Gradients
Figure: Gradients

This chapter covered Cairo shapes and fills.





PyGobject(九十三)Cairo系列——简介&简单示例

Cairo 安装 Cairo在PyGobject中的使用 简单示例 Cairo Cario是一个2D图形库,支持多种输出设备。 目前支持的输出目标包括X Window,Quartz,Win3...
  • a87b01c14
  • a87b01c14
  • 2016年08月03日 08:58
  • 1492

cairo学习简单总结

Cairo将成为Linux 2D 绘图的未来 内容: 1,什么是Cairo 2.理解cairo 3.常用函数 4.常用代码片断举例 注意:目...
  • hetangbian
  • hetangbian
  • 2016年08月25日 10:37
  • 753

Cairo 图形指南 (4) —— 基本绘图

这一部分讲述如何绘制一些简单的图元,包括直线、填充与笔画操作、虚线、线端(Cap)与线的交合等图形的绘制方法。 直线段 直线段是非常基础的矢量图形对象。画一条直线段,需要调用两个函数:ca...
  • jiangnanyidiao
  • jiangnanyidiao
  • 2014年10月21日 18:07
  • 711

使用cairo绘制图形的部分函数总结

一 绘制文本 [cpp] view plain copy //设置源的颜色   cairo_set_source_rgb(cr,0.627,0,0...
  • xingzouagain
  • xingzouagain
  • 2016年09月11日 11:55
  • 1025

Cairo开发环境安装与在VC++2012中简单实现

     最近有一个任务就是利用vc++将设计好的地图生成pdf文件,于是开始零基础接触Cairo库,边学边整理吧。这是自己一开始Cairo环境安装与一个简单的实现例子,算是我这种菜鸟级别的...
  • Shixi_vivian
  • Shixi_vivian
  • 2016年10月16日 17:50
  • 414

14、交叉编译cairo

14、交叉编译cairo 目标平台:LOONGSON-1B开发板 内核:Linux 3.0 编译平台:ubuntu10.04 交叉工具链:gcc-3.4.6-2f   一、简介   ...
  • water_cow
  • water_cow
  • 2013年03月27日 20:15
  • 4348

PyGobject(九十五)Cairo系列——渐变

渐变分为线性渐变和径向渐变需要用到cairo.Pattern类cairo.PatternPatterns are the paint with which cairo draws. The prima...
  • a87b01c14
  • a87b01c14
  • 2016年08月03日 10:36
  • 1297

PyGobject(一百)Cairo系列——cairo.Surface实现图片倒影

cairoSurface class cairoSurface copy_page create_similarcontent width height finish flush get_conten...
  • a87b01c14
  • a87b01c14
  • 2016年08月03日 11:17
  • 1587

Cairo 图形指南 (6) —— 透明

这一篇讲述有关透明的一些基本知识,并提供两个有趣的透明效果。 透明是透过某种材质的可见度。理解透明最简单的方式就是想像一下玻璃或者水。从技术上讲,光线可以穿过玻璃,因此我们可以看到玻璃之后的物体...
  • jiangnanyidiao
  • jiangnanyidiao
  • 2014年10月21日 18:12
  • 881

cairo简单使用指南

git clone ssh://rocket.he@165.213.149.219:29418/magnolia/framework/graphics/chart-demo cairo cairo.h...
  • sinat_28502203
  • sinat_28502203
  • 2015年05月26日 17:05
  • 375
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:The Cairo graphics tutorial -------Shapes and fills in Cairo
举报原因:
原因补充:

(最多只允许输入30个字)