• Cairo编程


    一、简介

    cairo 是一个免费的矢量绘图软件库,它可以绘制多种输出格式。cairo 支持许多平台,包括 Linux、BSD、Microsoft® Windows® 和 OSX(BeOS 和 OS2 后端也正在开发)。Linux 绘图可以通过 X Window 系统、Quartz、图像缓冲格式或 OpenGL 上下文来实现。另外,cairo 还支持生成 PostScript 或 PDF 输出,从而产生高质量的打印结果。在理想情况下,cairo 的用户可以在打印机和屏幕上获得非常接近的输出效果。

    专业术语

     

    1、环境 (Context)
    使用 Cairo 绘图,必须要首先创建 Cairo 环境 (Context)。Cairo 环境保存着所有的图形状态参数,这些参数描述了图形的构成,譬如线条宽度、颜色、要绘制的外观 (Surface) 以及其它一些信息。Cairo 环境允许真正的绘图函数使用很少的一部分参数,以此提高接口的易用性。调用 gdk_cairo_create () 函数可为所绘制的图形创建一个 Cairo 环境。

    cairo_t * cr;
    cr = gdk_cairo_create (widget->window);

    这两行代码创建了一个 Cairo 环境,并且这个 Cairo 环境是关联到 GdkDrawable 对象上的。cairo_t 结构体包含了当前渲染设备的状态,也包含了所绘制图形的坐标。从技术上来讲,cairo_t 就是所谓的 Cairo 环境。

    Cairo 所有的绘图函数都要去操作 cairo_t 对象。一个 Cairo 环境可以被关联到一种特定的外观,譬如 pdf、svg、png、GdkDrawable 等。

    GDK 没有对 Cairo API 进行封装,它只允许创建一个可基于 GdkDrawable 对象绘制图形的 Cairo 环境。有一些 GDK 函数可以将 GDK 的矩形或填充区域转换为 Cairo Path (路径),然后使用 Cairo 绘图与渲染。

    2、路径 (Path)
    一条 Path(路径)通常是由一条或多条首尾相接的直线段构成的,也可以由直线段与曲线段构成。路径可分为 Open(开放)类型与 Closed(闭合)类型,前者的首尾端点不重合,后者的首尾端点重合。

    在 Cairo 中,绘图要从一条空路径开始,首先定义一条路径,然后通过绘制/填充操作使之可见。要注意的是,每次调用 cairo_stroke () 或 cairo_fill () 函数之后,路径会被清空,不得不再定义新的路径。
    一条路径可由一些子路径构成。

    3、源 (Source)
    源好比绘图中所使用的画笔/颜料,使用它来绘制/填充图形轮廓。有 4 种基本的源:color、gradient、pattern 与 image。

    4、外观 (Surface)
    Surface 就是要绘制图形的最终体现形式,譬如可使用 PDF 或 PostScript 外观实现文本内容的渲染,或者使用 Xlib、Win32 外观实现屏幕绘图。
    Cairo 具体有那些外观类型,可参考其定义:

    typedef enum _cairo_surface_type {
      CAIRO_SURFACE_TYPE_IMAGE,
      CAIRO_SURFACE_TYPE_PDF,
      CAIRO_SURFACE_TYPE_PS,
      CAIRO_SURFACE_TYPE_XLIB,
      CAIRO_SURFACE_TYPE_XCB,
      CAIRO_SURFACE_TYPE_GLITZ,
      CAIRO_SURFACE_TYPE_QUARTZ,
      CAIRO_SURFACE_TYPE_WIN32,
      CAIRO_SURFACE_TYPE_BEOS,
      CAIRO_SURFACE_TYPE_DIRECTFB,
      CAIRO_SURFACE_TYPE_SVG,
      CAIRO_SURFACE_TYPE_OS2
    } cairo_surface_type_t;

    5、蒙板 (Mask)
    在源作用于外观之前,可对其实现过滤,蒙板 (mask) 即是过滤器。蒙板决定哪些源可被显示。蒙板不透明的部分允许复制源至外观,蒙板透明的部分则禁止复制源至外观。、

    6、图案 (Pattern)
    图案表示被绘制到外观的源。在 Cairo 中,图案是一种可以读取的内容,可用作绘图操作的源或蒙板。图案可以是纯色模式、基于外观的模式以及渐变模式。

     

     

    二、编译与安装

    参考:http://cairographics.org/download/

    执行以下命令,即可完成安装

    sudo yum install cairo-devel
    如下图

    image

    三、编程

    程序1:用于生成 PNG 图像

    #include <cairo.h>
    
    int main (int argc, char *argv[])
    {
            cairo_surface_t *surface;
            cairo_t *cr;
    
            surface =cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 400, 800);
            cr = cairo_create (surface);
    
            cairo_set_source_rgb (cr, 1, 0, 0);
            cairo_rectangle(cr,0,0,400,800);
            cairo_fill(cr);
             cairo_select_font_face (cr, "Adobe Heiti Std", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
            cairo_set_font_size (cr, 30.0);
    
            cairo_move_to (cr, 100, 400);
            cairo_set_source_rgb (cr, 0, 1, 0);
            cairo_show_text (cr, "I Love Chinese !");
    
            cairo_surface_write_to_png (surface, "image.png");
    
            cairo_destroy (cr);
            cairo_surface_destroy (surface);
    
            return 0;
    }

    编译

    gcc -o example-1.o example-1.c -lcairo -I/usr/include/cairo

    运行

    image

    程序2:用于生成 PDF 图像

    #include <cairo.h>
    #include <cairo-pdf.h>
    
    int main (int argc, char *argv[])
    {
            cairo_surface_t *surface;
            cairo_t *cr;
    
            surface = cairo_pdf_surface_create ("pdffile.pdf", 20, 40);
            cr = cairo_create (surface);
    
            cairo_set_source_rgb (cr, 1, 0, 0);
            cairo_rectangle(cr,0,0,20,40);
            cairo_fill(cr);
             cairo_select_font_face (cr, "WenQuanYi Zen Hei", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
            cairo_set_font_size (cr, 5);
    
            cairo_move_to (cr, 0, 20);
            cairo_set_source_rgb (cr, 0, 1, 0);
            cairo_show_text (cr, "热爱编程");
    
            cairo_show_page (cr);
    
            cairo_destroy (cr);
            cairo_surface_destroy (surface);
    
            return 0;
    }

    编译

    gcc -o example-2.o example-2.c -lcairo -I/usr/include/cairo

    运行

    image

    程序3:用于生成 SVG 图像

    #include <cairo.h>
    #include <cairo-svg.h>
    
    int main (int argc, char *argv[])
    {
            cairo_surface_t *surface;
            cairo_t *cr;
    
            surface = cairo_svg_surface_create ("svgfile.svg", 20, 40);
            cr = cairo_create (surface);
    
            cairo_set_source_rgb (cr, 1, 0, 0);
            cairo_rectangle(cr,0,0,20,40);
            cairo_fill(cr);
             cairo_select_font_face (cr, "WenQuanYi Zen Hei", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
            cairo_set_font_size (cr, 5);
    
            cairo_move_to (cr, 0, 20);
            cairo_set_source_rgb (cr, 0, 1, 0);
            cairo_show_text (cr, "热爱编程");
    
            cairo_destroy (cr);
            cairo_surface_destroy (surface);
    
            return 0;
    }

    编译

    gcc -o example-3.o example-3.c -lcairo -I/usr/include/cairo

    运行

    image

    程序4:在 GTK 窗口中使用 Cairo 绘制图形

    要在 GTK+ 窗口中绘制 Cairo 图形,可以使用 GtkDrawingArea widget 或者更为简单的 GtkWindow widget,本例选择 GtkWindow 。由 GtkWindow widget 对 expose-event 信号处理后,默认要重新绘制窗口背景,这会将我们在 on_expose_event () 函数中定义的 Cairo 图形覆盖掉,因此需要调用 gtk_widget_set_app_paintable () 函数通知 GTK+ 不要这么干。如果是在 GtkDrawingArea widget 中绘制 Cairo 图形,则可省区这一步。

    #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);
    
        cairo_set_source_rgb (cr, 0.627, 0, 0);
        cairo_select_font_face (cr, "WenQuanYi Zen Hei", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
        cairo_set_font_size (cr, 24.0);
    
        cairo_move_to (cr, 10.0, 34.0);
        cairo_show_text (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 (window, "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), 320, 48);
        gtk_widget_set_app_paintable (window, TRUE);
    
        gtk_widget_show_all (window);
    
        gtk_main ();
    
        return 0;
    }

    编译

    gcc -o example-5.o example-5.c -lcairo -I/usr/include/cairo `pkg-config --cflags --libs gtk+-2.0`

    运行

    image

    程序5:绘制动态图形

    #include <cairo.h>
    #include <gtk/gtk.h>
    #include <math.h>
    
    cairo_surface_t *image;
    
    static gboolean on_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
    {
        cairo_t *cr;
    
        static gint pos_x = 128;
        static gint pos_y = 128;
        gint radius = 40;
    
        static gint delta[] = { 3, 3 };
    
        cr = gdk_cairo_create(widget->window);
    
        gint width, height;
        gtk_window_get_size(GTK_WINDOW(widget), &width, &height);
    
        if (pos_x < 0 + radius)
        {
            delta[0] = rand() % 4 + 5;
        }
        else if (pos_x > width - radius)
        {
            delta[0] = -(rand() % 4 + 5);
        }
    
        if (pos_y < 0 + radius)
        {
            delta[1] = rand() % 4 + 5;
        }
        else if (pos_y > height - radius)
        {
            delta[1] = -(rand() % 4 + 5);
        }
    
        pos_x += delta[0];
        pos_y += delta[1];
    
        cairo_set_source_surface(cr, image, 1, 1);
        cairo_arc(cr, pos_x, pos_y, radius, 0, 2*M_PI);
        cairo_clip(cr);
        cairo_paint(cr);
    
        cairo_destroy(cr);
    
        return FALSE;
    }
    
    static gboolean time_handler (GtkWidget *widget)
    {
        if (widget->window == NULL) return FALSE;
        gtk_widget_queue_draw(widget);
        return TRUE;
    }
    
    int main(int argc, char *argv[])
    {
        GtkWidget *window;
        gint width, height;
    
        image = cairo_image_surface_create_from_png("turnacastle.png");
        width = cairo_image_surface_get_width(image);
        height = cairo_image_surface_get_height(image);
    
    
        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), width+2, height+2);
    
        gtk_widget_set_app_paintable(window, TRUE);
        gtk_widget_show_all(window);
        g_timeout_add(100, (GSourceFunc) time_handler, (gpointer) window);
    
        gtk_main();
    
        cairo_surface_destroy(image);
    
        return 0;
    }

    编译

    gcc -o example-6.o example-6.c -lcairo -I/usr/include/cairo `pkg-config --cflags --libs gtk+-2.0`

    运行

    image

    程序6:相交区域处理示例

    #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);
    
        static gboolean xdirection = TRUE;
        static gint counter = 0;
    
        int width, height;
        gtk_window_get_size(GTK_WINDOW(widget), &width, &height);
    
        static gdouble rotate = 0;
    
        static gint bigx = 20;
        static gint bigy = 200;
        static gint delta = 1;
    
        counter += 1;
    
    
        if (bigx > width)
        {
            xdirection = FALSE;
            delta = -delta;
            bigx = width;
        }
    
        if (bigx < 1)
        {
            bigx = 1;
            delta = -delta;
        }
    
        if (bigy > height)
        {
            xdirection = TRUE;
            delta = -delta;
            bigy = height;
        }
    
        if (bigy < 1)
        {
            delta = -delta;
            bigy = 1;
        }
    
        if (xdirection)
        {
            bigx += delta;
        }
        else
        {
            bigy += delta;
        }
    
        cairo_translate(cr, width / 2, height /2);
    
        cairo_rectangle(cr, -bigx/2, -bigy/2, bigx-2, bigy-2);
        cairo_set_source_rgb(cr, 0, 0, 0);
        cairo_set_line_width(cr, 1);
        cairo_stroke(cr);
    
        cairo_rotate(cr, rotate);
        rotate += 0.01;
    
        cairo_rectangle(cr, -50, -25, 100, 50);
        cairo_stroke(cr);
    
        GdkRectangle bigrect;
        GdkRectangle rect;
        GdkRectangle intersect;
    
        bigrect.x = -bigx/2;
        bigrect.y = -bigy/2;
        bigrect.width = bigx -2;
        bigrect.height = bigy -2;
    
        rect.x = -50;
        rect.y = -25;
        rect.width = 100;
        rect.height = 50;
    
        gdk_rectangle_intersect(&bigrect, &rect, &intersect);
        cairo_rectangle(cr, intersect.x, intersect.y, intersect.width, intersect.height);
        cairo_fill(cr);
    
        cairo_destroy(cr);
    
        return FALSE;
    }
    
    static gboolean time_handler (GtkWidget *widget)
    {
        if (widget->window == NULL) return FALSE;
        gtk_widget_queue_draw(widget);
        return TRUE;
    }
    
    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), 250, 200);
    
        gtk_widget_set_app_paintable(window, TRUE);
        gtk_widget_show_all(window);
        g_timeout_add(5, (GSourceFunc) time_handler, (gpointer) window);
    
        gtk_main();
    
        return 0;
    }

    编译

    gcc -o example-7.o example-7.c -lcairo -I/usr/include/cairo `pkg-config --cflags --libs gtk+-2.0`

    运行

    image

    程序7:遮蔽应用示例

    #include <cairo.h>
    #include <gtk/gtk.h>
    
    static gboolean on_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
    {
        cairo_t *cr;
        cairo_surface_t *surface;
    
        cr = gdk_cairo_create(widget->window);
    
        cairo_set_source_rgb(cr, 0, 0, 0);
    
        surface = cairo_image_surface_create_from_png("omen.png");
        cairo_mask_surface(cr, surface, 0, 0);
        cairo_fill(cr);
    
        cairo_surface_destroy(surface);
        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), 305, 100);
    
        gtk_window_set_title(GTK_WINDOW(window), "mask");
        gtk_widget_set_app_paintable(window, TRUE);
        gtk_widget_show_all(window);
    
        gtk_main();
    
        return 0;
    }

    编译

    gcc -o example-8.o example-8.c -lcairo -I/usr/include/cairo `pkg-config --cflags --libs gtk+-2.0`

    运行

    image

    程序8:平移变换示例

    #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);
    
        cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
        cairo_rectangle(cr, 20, 20, 80, 50);
        cairo_stroke_preserve(cr);
        cairo_set_source_rgb(cr, 1, 1, 1);
        cairo_fill(cr);
    
        cairo_translate(cr, 100, 100);     //通过平移用于空间的原点来修改当前的变换矩阵
    
        cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
        cairo_rectangle(cr, 20, 20, 80, 50);
        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;
    
        gtk_init(&argc, &argv);
    
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    
        g_signal_connect(window, "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), 300, 230);
        gtk_widget_set_app_paintable(window, TRUE);
    
        gtk_widget_show_all(window);
    
        gtk_main();
    
        return 0;
    }

    编译

    gcc -o example-9.o example-9.c -lcairo -I/usr/include/cairo `pkg-config --cflags --libs gtk+-2.0`

    运行

    image

    程序9:旋转变换示例

    #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.6, 0.6, 0.6);
        cairo_rectangle(cr, 20, 20, 80, 50);
        cairo_stroke_preserve(cr);
        cairo_set_source_rgb(cr, 1, 1, 1);
        cairo_fill(cr);
    
        cairo_translate(cr, 150, 100);
        cairo_rotate(cr, M_PI/2);   //围绕原点旋转180°
    
        cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
        cairo_rectangle(cr, 20, 20, 80, 50);
        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;
    
        gtk_init(&argc, &argv);
    
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    
        g_signal_connect(window, "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), 300, 230);
        gtk_widget_set_app_paintable(window, TRUE);
    
        gtk_widget_show_all(window);
    
        gtk_main();
    
        return 0;
    }

    编译

    gcc -o example-10.o example-10.c -lcairo -I/usr/include/cairo `pkg-config --cflags --libs gtk+-2.0`

    运行

    image

    程序10:缩放变换示例

    #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);
    
        cairo_save(cr);
        cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
        cairo_rectangle(cr, 20, 30, 80, 50);
        cairo_stroke_preserve(cr);
        cairo_set_source_rgb(cr, 1, 1, 1);
        cairo_fill(cr);
        cairo_restore(cr);
    
        cairo_save(cr);
        cairo_translate(cr, 130, 30);
        cairo_scale(cr, 0.7, 0.7);    //对图形进行缩小操作
    
        cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
        cairo_rectangle(cr, 0, 0, 80, 50);
        cairo_stroke_preserve(cr);
        cairo_set_source_rgb(cr, 1, 1, 1);
        cairo_fill(cr);
        cairo_restore(cr);
    
        cairo_save(cr);
        cairo_translate(cr, 220, 30);
        cairo_scale(cr, 1.5, 1.5);    //对图形进行放大操作 
    
        cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
        cairo_rectangle(cr, 0, 0, 80, 50);
        cairo_stroke_preserve(cr);
        cairo_set_source_rgb(cr, 1, 1, 1);
        cairo_fill(cr);
        cairo_restore(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(window, "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), 360, 140);
        gtk_widget_set_app_paintable(window, TRUE);
    
        gtk_widget_show_all(window);
    
        gtk_main();
    
        return 0;
    }

    编译

    gcc -o example-11.o example-11.c -lcairo -I/usr/include/cairo `pkg-config --cflags --libs gtk+-2.0`

    运行

    image

    程序11:错切变换示例

    #include <cairo.h>
    #include <gtk/gtk.h>
    
    
    static gboolean on_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
    {
        cairo_t *cr;
        cairo_matrix_t matrix;
    
        cr = gdk_cairo_create (widget->window);
    
        cairo_save(cr);
        cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
        cairo_rectangle(cr, 20, 30, 80, 50);
        cairo_stroke_preserve(cr);
        cairo_set_source_rgb(cr, 1, 1, 1);
        cairo_fill(cr);
        cairo_restore(cr);
    
        cairo_save(cr);
        cairo_translate(cr, 130, 30);
        cairo_matrix_init(&matrix,
                          1.0, 0.5,
                          0.0, 1.0,
                          0.0, 0.0);
    
        cairo_transform (cr, &matrix);
    
        cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
        cairo_rectangle(cr, 0, 0, 80, 50);
        cairo_stroke_preserve(cr);
        cairo_set_source_rgb(cr, 1, 1, 1);
        cairo_fill(cr);
        cairo_restore(cr);
    
        cairo_save(cr);
        cairo_translate(cr, 220, 30);
        cairo_matrix_init(&matrix,
                          1.0, 0.0,
                          0.7, 1.0,
                          0.0, 0.0);
    
        cairo_transform(cr, &matrix);
    
        cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
        cairo_rectangle(cr, 0, 0, 80, 50);
        cairo_stroke_preserve(cr);
        cairo_set_source_rgb(cr, 1, 1, 1);
        cairo_fill(cr);
        cairo_restore(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(window, "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), 360, 140);
        gtk_widget_set_app_paintable(window, TRUE);
    
        gtk_widget_show_all(window);
    
        gtk_main();
    
        return 0;
    }

    编译

    gcc -o example-12.o example-12.c -lcairo -I/usr/include/cairo `pkg-config --cflags --libs gtk+-2.0`

    运行

    image

  • 相关阅读:
    oracle 数据库服务名怎么查
    vmware vsphere 6.5
    vSphere虚拟化之ESXi的安装及部署
    ArcMap中无法添加ArcGIS Online底图的诊断方法
    ArcGIS中字段计算器(高级计算VBScript、Python)
    Bad habits : Putting NOLOCK everywhere
    Understanding the Impact of NOLOCK and WITH NOLOCK Table Hints in SQL Server
    with(nolock) or (nolock)
    What is “with (nolock)” in SQL Server?
    Changing SQL Server Collation After Installation
  • 原文地址:https://www.cnblogs.com/274914765qq/p/4364261.html
Copyright © 2020-2023  润新知