memo:Cairo 绘图

Cairo:http://cairographics.org/  是一款绘图工具。前面在安装munin的时候发现需要这个东东。

概述:

Cairo is a 2D graphics library with support for multiple outputdevices. Currently supported output targets include the XWindow System, Quartz, Win32, image buffers, PostScript, PDF, and SVGfile output. Experimental backends include OpenGL, XCB, BeOS, OS/2,and DirectFB.

Cairo is designed to produce consistent output on all output mediawhile taking advantage of display hardware acceleration when available(eg. through the X Render Extension).

The cairo API provides operations similar to the drawingoperators of PostScript and PDF. Operations in cairo includingstroking and filling cubic Bézier splines, transforming andcompositing translucent images, and antialiased text rendering. Alldrawing operations can be transformed by any affine transformation(scale, rotation, shear, etc.)

Cairo is implemented as a library written in the C programminglanguage, but bindings are available for several differentprogramming languages.

Cairo is free software and is available to be redistributedand/or modified under the terms of either the GNU Lesser GeneralPublic License (LGPL) version 2.1 or the Mozilla Public License (MPL)version 1.1 at your option.


具体的解释来自:http://hi.baidu.com/weihuoya/blog/item/6944a5117feec7e0c2ce798d.html

使用 Cairo 绘图,首先需要创建 surface,Cairo 支持的 surface 有:

PDF:    cairo_surface_t * cairo_pdf_surface_create (const char *filename, double width_in_points, double height_in_points);

图片:    cairo_surface_t * cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);

PNG:    cairo_surface_t * cairo_image_surface_create_from_png (const char *filename);

win32 HDC:    cairo_surface_t * cairo_win32_surface_create (HDC hdc);

若要在 Gtk+ 程序上绘图,则可用 Gtk+ 提供的函数。

 

创建了 surface 后,需要在这个 surface 上创建绘图的上下文 cairo_t :   cairo_t * cairo_create ( cairo_surface_t * surface );

Gtk+ 程序则可以从 GdkDrawable 创建一个 绘图上下文,Gtk+ 的控件 GtkWidget 结构体中,有一个 GdkWindow window,

而 GdkWindow 就是 GdkDrawable,在 Gdk 的头文件中有这样的定义: typedef GdkDrawable GdkWindow;

所以要在 Gtk+ 控件绘图,可以直接在控件上创建一个绘图上下文: cairo_t * cr = gdk_cairo_create(widget->window);

 

在 Gtk+ 控件上绘图步骤:

1、首先定义一个控件

2、gtk_widget_set_app_paintable ( widget, TRUE );   //告诉 Gtk+ ,程序会在控件上绘图

3、g_signal_connect ( widdget, "expose-event", G_CALLBACK (on_expose_event), NULL );   //在控件绘制消息中,绘图

4、定义 gboolean  on_expose_event (GtkWidget * widget, GdkEventExpose * event, gpointer data)  //事件响应函数

5、cairo_t * cr = gdk_cairo_create (widget->window);  //创建绘图上下文,开始绘图

6、cairo_destroy(cr);   //释放资源

 

在 Win32 环境下绘图:

1、定义窗口过程函数:LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

2、响应 WM_PAINT 消息,创建设备描述表:

    HDC hdc;

    PAINTSTRUCT ps;

    hdc = BeginPaint(hwnd, &ps);

3、从 HDC 创建 Cairo 绘图上下文:

    cairo_surface_t * surface = cairo_win32_surface_create(hdc);

    cairo_t * cr = cairo_create(surface);

4、开始绘图

5、释放资源:

    cairo_destroy(cr);

    cairo_surface_destroy(surface);

    EndPaint(hwnd, &ps);

 

 

绘制完毕后,需要释放资源,对于 图片 和 PDF 还需要输出文件:

void cairo_destroy( cairo_t * cr);

void cairo_surface_destroy( cairo_surface_t * surface);

 

void cairo_show_page ( cairo_t * cr); //输出 PDF 文件

cairo_status_t  cairo_surface_write_to_png (cairo_surface_t *surface, const char  *filename);  //输出 PNG 文件

 

 

Cairo 的绘图方式:

Cairo 绘图可以简单的分为3层:source - 源、path - 路径 / mask - 蒙板、context - 上下文

source 可以是 颜色(color)、图像(image)、图案(pattern)

path / mask 则是决定那一部分 source 绘制到 context 上

context 就是画布了

 

将 source 绘制到 context 上有3种方式:stroke、fill、paint

stroke:描边,即按着 path ,将线条绘制到 context 上

fill:在 path 的封闭形状中,将 source 绘制到 context 上

paint:直接将 source 绘制到 context 上

 

相关函数:

source:

void cairo_set_source (cairo_t *cr, cairo_pattern_t *source);   //设置图案作为源

void cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue);  //设置颜色作为源

void cairo_set_source_rgba (cairo_t *cr, double red, double green, double blue, double alpha);  //设置有 alpha 通道的颜色作为源

void cairo_set_source_surface (cairo_t   *cr, cairo_surface_t *surface, double  x, double  y);   //设置图像作为源

绘制:

void cairo_stroke (cairo_t *cr);  //描边,并清空 path

void cairo_stroke_preserve (cairo_t *cr);  //描边,并保留 path

 void cairo_fill (cairo_t *cr);  //填充,并清空 path

void cairo_fill_preserve (cairo_t *cr); //填充,并保留 path

void cairo_paint (cairo_t *cr); //绘制

void cairo_paint_with_alpha (cairo_t *cr, double   alpha); //绘制,并带 alpha 通道

 

 

Cairo 中的几个绘制图形时使用的函数:

void cairo_move_to (cairo_t *cr, double x, double y);  //改变绘制起始点

void cairo_line_to (cairo_t *cr, double x, double y);   //绘制直线

void cairo_arc (cairo_t *cr,  double xc, double yc, double radius, double start_angle, double end_angle);  //绘制弧线

void cairo_rectangle (cairo_t *cr, double x, double y, double width, double height);  //绘制长方形

void cairo_curve_to (cairo_t *cr, double x1, double y1, double x2, double y2, double x3, double y3);  //绘制曲线

void cairo_show_text (cairo_t *cr, const char *text);  //绘制文字

 

Cairo 绘图例,实现功能为在鼠标选择的区域绘制一个长方形:

//全局变量

 gboolean select_active;

//前向声明

static gboolean on_event_press (GtkWidget *widget, GdkEventButton *bev, GdkRectangle *sel_info);
static gboolean on_event_release(GtkWidget *widget, GdkEventButton *bev, GdkRectangle *sel_info);
static gboolean on_event_motion (GtkWidget *widget, GdkEventMotion *mev, GdkRectangle *sel_info);

 

//main函数

gint main (gint argc, gchar **argv)
{
GtkWidget *window;
GtkWidget *canvas;
GdkRectangle selection = {0, 0, 0, 0};

gtk_init (&argc, &argv);

window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (G_OBJECT (window), "delete-event", G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

canvas = gtk_drawing_area_new ();
gtk_widget_set_size_request (canvas, 400, 300);


g_signal_connect (G_OBJECT (canvas), "expose-event", G_CALLBACK (on_expose_event), &selection);

//给画布添加响应的事件
gtk_widget_add_events (canvas, GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);

//添加事件响应函数
  g_signal_connect (G_OBJECT (canvas), "button_press_event", G_CALLBACK (on_event_press), &selection );
  g_signal_connect (G_OBJECT (canvas), "button_release_event", G_CALLBACK (on_event_release), &selection );
  g_signal_connect (G_OBJECT (canvas), "motion_notify_event", G_CALLBACK (on_event_motion), &selection);

gtk_container_add (GTK_CONTAINER (window), canvas);
gtk_widget_show_all (window);
gtk_main ();

return 0;
}

 

void on_expose_event (GtkWidget *widget, GdkEventExpose *eev, GdkRectangle *sel_info)
{
cairo_t *cr;

cr = gdk_cairo_create (widget->window);

cairo_set_source_rgb (cr, 1,1,1);
cairo_paint (cr);

cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);

cairo_save (cr);
cairo_set_font_size (cr, 20);
cairo_move_to (cr, 40, 60);
cairo_set_source_rgb (cr, 0,0,0);
cairo_show_text (cr, "Drag your mouse here");
cairo_restore (cr);

cairo_set_source_rgb (cr, 1,0,0);
cairo_set_font_size (cr, 15);
cairo_move_to (cr, 50, 100);
cairo_show_text (cr, "(and see alpha blended selection)");


cairo_stroke (cr);

    //绘制选择的区域
    if(TRUE == select_active)
    {
    cairo_rectangle (cr, sel_info->x, sel_info->y, sel_info->w, sel_info->h);

    cairo_set_source_rgba (cr, 0, 0, 1, 0.2);
    cairo_fill_preserve (cr);

    cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
    cairo_stroke (cr);
    }

cairo_destroy (cr);
}


gboolean on_event_press (GtkWidget *widget, GdkEventButton *bev, GdkRectangle *sel_info)
{
select_active = TRUE;

sel_info->x = bev->x;
sel_info->y = bev->y;
sel_info->w = 0;
sel_info->h = 0;
//重绘控件
gtk_widget_queue_draw (widget);

return TRUE;
}


gboolean on_event_motion (GtkWidget *widget, GdkEventMotion *mev, GdkRectangle *sel_info)
{
sel_info->w = mev->x - sel_info->x;
sel_info->h = mev->y - sel_info->y;

gtk_widget_queue_draw (widget);
return TRUE;
}

gboolean on_event_release (GtkWidget *widget, GdkEventButton *bev, GdkRectangle *sel_info)
{
select_active = FALSE;

gtk_widget_queue_draw (widget);
return TRUE;
}

 

 

 

在 Cairo 绘图环境中使用 Pango(Pango 可用于文字的绘制和布局,能够实现文字的对齐,缩进,样式设置):

首先从 Cairo 绘图上下文创建 Pango Layout:   PangoLayout *pango_cairo_create_layout (cairo_t     *cr);

若是在 Gtk+ 程序中,则可以使用函数:

PangoLayout * gtk_widget_create_pango_layout ( GtkWidget *widget, const char *text); //text 可以是 NULL

得到 PangoLayout

 

释放 Pango Layout 资源: void   g_object_unref (gpointer      object);

 

    cairo_t * cr;

    PangoLayout * layout;

    PangoFontDescription * font_desc;

    char font_name[] = "Microsoft Yahei";

    char text[] = "Hello Pango!";

    int font_size = 10;

 

    layout = pango_cairo_create_layout(cr);  //创建 Pango Layout

    cairo_move_to(cr, 20, 20);   //设置 Pango 绘制的起始点

 

    font_desc = pango_font_description_from_string(font_name);  //取得字体

    pango_font_description_set_size(font_desc, font_size);  //设置字体大小

 

    pango_layout_set_width(layout, PANGO_SCALE * width );   //设置文本显示可用的宽度

    pango_layout_set_wrap(layout, PANGO_WRAP_CHAR);   //设置换行方式

    pango_layout_set_indent(layout, 2 * PANGO_SCALE * font_size);   //设置段落缩进

    pango_layout_set_font_description(layout, font_desc);  //设置字体

    pango_layout_set_text(layout, text, -1);   //设置要显示的内容

 

    pango_font_description_free(font_desc);  //释放字体资源



你可能感兴趣的:(memo:Cairo 绘图)