第一个示例是在 GTK+ 窗口中显示《灵魂伙伴》的部分歌词。
01.
#include <cairo.h>
02.
#include <gtk/gtk.h>
03.
04.
05.
static
gboolean
06.
on_expose_event(GtkWidget *widget,
07.
GdkEventExpose *event,
08.
gpointer data)
09.
{
10.
cairo_t *cr;
11.
12.
cr = gdk_cairo_create(widget->window);
13.
14.
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
15.
16.
cairo_select_font_face(cr,
"Purisa"
,
17.
CAIRO_FONT_SLANT_NORMAL,
18.
CAIRO_FONT_WEIGHT_BOLD);
19.
20.
cairo_set_font_size(cr, 13);
21.
22.
cairo_move_to(cr, 20, 30);
23.
cairo_show_text(cr,
"Most relationships seem so transitory"
);
24.
cairo_move_to(cr, 20, 60);
25.
cairo_show_text(cr,
"They're all good but not the permanent one"
);
26.
27.
cairo_move_to(cr, 20, 120);
28.
cairo_show_text(cr,
"Who doesn't long for someone to hold"
);
29.
30.
cairo_move_to(cr, 20, 150);
31.
cairo_show_text(cr,
"Who knows how to love you without being told"
);
32.
cairo_move_to(cr, 20, 180);
33.
cairo_show_text(cr,
"Somebody tell me why I'm on my own"
);
34.
cairo_move_to(cr, 20, 210);
35.
cairo_show_text(cr,
"If there's a soulmate for everyone"
);
36.
37.
cairo_destroy(cr);
38.
39.
return
FALSE;
40.
}
41.
42.
43.
44.
int
main (
int
argc,
char
*argv[])
45.
{
46.
GtkWidget *window;
47.
48.
gtk_init(&argc, &argv);
49.
50.
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
51.
52.
g_signal_connect(window,
"expose-event"
,
53.
G_CALLBACK(on_expose_event), NULL);
54.
g_signal_connect(window,
"destroy"
,
55.
G_CALLBACK(gtk_main_quit), NULL);
56.
57.
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
58.
gtk_window_set_default_size(GTK_WINDOW(window), 420, 250);
59.
gtk_window_set_title(GTK_WINDOW(window),
"Soulmate"
);
60.
gtk_widget_set_app_paintable(window, TRUE);
61.
62.
gtk_widget_show_all(window);
63.
64.
gtk_main();
65.
66.
return
0;
67.
}
在这个示例中,显示了 Natasha Bedingfield 的《灵魂伙伴》的部分歌词。(在这里 ,可以听这首歌,很美妙)
1.
cairo_select_font_face(cr,
"Purisa"
,
2.
CAIRO_FONT_SLANT_NORMAL,
3.
CAIRO_FONT_WEIGHT_BOLD);
这里设置字体。这个函数接受了三个字体参数的传入,字体的名称、样式与轻重。
1.
cairo_set_font_size(cr, 13);
这里设定字号。
1.
cairo_move_to(cr, 20, 30);
2.
cairo_show_text(cr,
"Most relationships seem so transitory"
);
通过在窗口中指定位置并调用 cairo_show_text() 函数显示文本。
一个字接一个字……
这种效果就是一个字一个字的显示,这些字的绘制存有时间差。
01.
#include <cairo.h>
02.
#include <gtk/gtk.h>
03.
04.
gpointer text[7] = {
"Z"
,
"e"
,
"t"
,
"C"
,
"o"
,
"d"
,
"e"
};
05.
gboolean timer = TRUE;
06.
07.
08.
static
gboolean
09.
on_expose_event(GtkWidget *widget,
10.
GdkEventExpose *event,
11.
gpointer data)
12.
{
13.
cairo_t *cr;
14.
cairo_text_extents_t extents;
15.
static
gint count = 0;
16.
17.
cr = gdk_cairo_create(widget->window);
18.
19.
cairo_select_font_face(cr,
"Courier"
,
20.
CAIRO_FONT_SLANT_NORMAL,
21.
CAIRO_FONT_WEIGHT_BOLD);
22.
23.
cairo_set_font_size(cr, 35);
24.
cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);
25.
26.
gint i;
27.
gint x = 0;
28.
29.
for
(i = 0; i < count; i++) {
30.
cairo_text_extents(cr, text[i], &extents);
31.
x += extents.width + 2;
32.
cairo_move_to(cr, x + 30, 50);
33.
cairo_show_text(cr, text[i]);
34.
}
35.
36.
count++;
37.
38.
if
(count == 8) {
39.
timer = FALSE;
40.
count = 0;
41.
}
42.
43.
cairo_destroy(cr);
44.
45.
return
FALSE;
46.
}
47.
48.
static
gboolean
49.
time_handler (GtkWidget *widget)
50.
{
51.
if
(widget->window == NULL)
return
FALSE;
52.
53.
if
(!timer)
return
FALSE;
54.
55.
gtk_widget_queue_draw(widget);
56.
return
TRUE;
57.
}
58.
59.
60.
int
main (
int
argc,
char
*argv[])
61.
{
62.
GtkWidget *window;
63.
64.
gtk_init(&argc, &argv);
65.
66.
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
67.
68.
g_signal_connect(window,
"expose-event"
,
69.
G_CALLBACK(on_expose_event), NULL);
70.
g_signal_connect(window,
"destroy"
,
71.
G_CALLBACK(gtk_main_quit), NULL);
72.
73.
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
74.
gtk_window_set_default_size(GTK_WINDOW(window), 300, 90);
75.
gtk_window_set_title(GTK_WINDOW(window),
"ZetCode"
);
76.
gtk_widget_set_app_paintable(window, TRUE);
77.
78.
g_timeout_add(1000, (GSourceFunc) time_handler, (gpointer) window);
79.
80.
gtk_widget_show_all(window);
81.
82.
83.
gtk_main();
84.
85.
return
0;
86.
}
在这个示例中,我们在 GTK+ 窗口中画了“ZetCode”这个字串,并让逐个字母伴随一定的时间差逐一显示。
1.
gpointer text[7] = {
"Z"
,
"e"
,
"t"
,
"C"
,
"o"
,
"d"
,
"e"
};
构造一个字符数组。
1.
cairo_select_font_face(cr,
"Courier"
,
2.
CAIRO_FONT_SLANT_NORMAL,
3.
CAIRO_FONT_WEIGHT_BOLD);
将字体设置为 Courier。
1.
for
(i = 0; i < count; i++) {
2.
cairo_text_extents(cr, text[i], &extents);
3.
x += extents.width + 2;
4.
cairo_move_to(cr, x + 30, 50);
5.
cairo_show_text(cr, text[i]);
6.
}
开始逐个字的绘制。extents.width 给出了当前字符的宽度。
膨胀
下面这个示例中,我们制造了一种膨胀的效果。这个示例显示了一串在膨胀的居中文本,并且伴有淡出现象。这是很常见的效果,在 flash 动画里经常见到。
01.
#include <cairo.h>
02.
#include <gtk/gtk.h>
03.
04.
05.
gpointer text[7] = {
"Z"
,
"e"
,
"t"
,
"C"
,
"o"
,
"d"
,
"e"
};
06.
gboolean timer = TRUE;
07.
08.
09.
static
gboolean
10.
on_expose_event(GtkWidget *widget,
11.
GdkEventExpose *event,
12.
gpointer data)
13.
{
14.
cairo_t *cr;
15.
cairo_text_extents_t extents;
16.
17.
static
gdouble alpha = 1.0;
18.
static
gdouble size = 1;
19.
20.
21.
gint x = widget->allocation.width / 2;
22.
gint y = widget->allocation.height / 2;
23.
24.
cr = gdk_cairo_create(widget->window);
25.
26.
cairo_set_source_rgb(cr, 0.5, 0, 0);
27.
cairo_paint(cr);
28.
29.
cairo_select_font_face(cr,
"Courier"
,
30.
CAIRO_FONT_SLANT_NORMAL,
31.
CAIRO_FONT_WEIGHT_BOLD);
32.
33.
size += 0.8;
34.
35.
if
(size > 20) {
36.
alpha -= 0.01;
37.
}
38.
39.
cairo_set_font_size(cr, size);
40.
41.
cairo_set_source_rgb(cr, 1, 1, 1);
42.
43.
cairo_text_extents(cr,
"ZetCode"
, &extents);
44.
cairo_move_to(cr, x - extents.width/2, y);
45.
cairo_text_path(cr,
"ZetCode"
);
46.
cairo_clip(cr);
47.
cairo_stroke(cr);
48.
cairo_paint_with_alpha(cr, alpha);
49.
50.
if
(alpha <= 0) {
51.
timer = FALSE;
52.
}
53.
54.
cairo_destroy(cr);
55.
56.
return
FALSE;
57.
}
58.
59.
static
gboolean
60.
time_handler (GtkWidget *widget)
61.
{
62.
if
(widget->window == NULL)
return
FALSE;
63.
64.
if
(!timer)
return
FALSE;
65.
66.
gtk_widget_queue_draw(widget);
67.
68.
return
TRUE;
69.
}
70.
71.
72.
int
main (
int
argc,
char
*argv[])
73.
{
74.
GtkWidget *window;
75.
76.
gtk_init(&argc, &argv);
77.
78.
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
79.
80.
g_signal_connect(window,
"expose-event"
,
81.
G_CALLBACK(on_expose_event), NULL);
82.
g_signal_connect(window,
"destroy"
,
83.
G_CALLBACK(gtk_main_quit), NULL);
84.
85.
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
86.
gtk_window_set_default_size(GTK_WINDOW(window), 350, 200);
87.
gtk_window_set_title(GTK_WINDOW(window),
"puff"
);
88.
gtk_widget_set_app_paintable(window, TRUE);
89.
90.
g_timeout_add(14, (GSourceFunc) time_handler, (gpointer) window);
91.
92.
gtk_widget_show_all(window);
93.
94.
gtk_main();
95.
96.
return
0;
97.
}
这个示例在 GTK+ 窗口中制造了一种膨胀并且淡出的文本渲染效果。
1.
gint x = widget->allocation.width / 2;
2.
gint y = widget->allocation.height / 2;
获取窗口中心坐标。
1.
cairo_set_source_rgb(cr, 0.5, 0, 0);
2.
cairo_paint(cr);
将背景设为暗红色。
1.
size += 0.8;
每轮循环,字号都增长 0.8 个单位。
1.
if
(size > 20) {
2.
alpha -= 0.01;
3.
}
当字号大于 20 的时候,就开始淡出。
1.
cairo_text_extents(cr,
"ZetCode"
, &extents);
获取文本尺寸。
1.
cairo_move_to(cr, x - extents.width/2, y);
根据文本尺寸来将文本定位在窗口的中心位置。
1.
cairo_text_path(cr,
"ZetCode"
);
2.
cairo_clip(cr);
获取文本的的路径,并将其设为当前的裁剪域。
1.
cairo_stroke(cr);
2.
cairo_paint_with_alpha(cr, alpha);
绘制当前的路径,并为之添加 alpha 值(可实现淡出效果)。