Cairo 图形指南 (2) —— 文本

来源:互联网 发布:电子地图数据采集软件 编辑:程序博客网 时间:2024/06/07 06:09
本篇讲述如何处理文本。

灵魂伙伴

第一个示例是在 GTK+ 窗口中显示《灵魂伙伴》的部分歌词。

[html] view plaincopyprint?
  1. #include <cairo.h>  
  2. #include <gtk/gtk.h>  
  3.    
  4. staticgboolean  
  5. on_expose_event(GtkWidget *widget,  
  6.     GdkEventExpose *event,  
  7.     gpointer data)  
  8. {  
  9.   cairo_t *cr;  
  10.    
  11.   cr = gdk_cairo_create(widget->window);  
  12.    
  13.   cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);  
  14.    
  15.   cairo_select_font_face(cr,"Purisa",  
  16.       CAIRO_FONT_SLANT_NORMAL,  
  17.       CAIRO_FONT_WEIGHT_BOLD);  
  18.    
  19.   cairo_set_font_size(cr, 13);  
  20.    
  21.   cairo_move_to(cr, 20, 30);  
  22.   cairo_show_text(cr,"Most relationships seem so transitory");   
  23.   cairo_move_to(cr, 20, 60);  
  24.   cairo_show_text(cr,"They're all good but not the permanent one");  
  25.    
  26.   cairo_move_to(cr, 20, 120);  
  27.   cairo_show_text(cr,"Who doesn't long for someone to hold");  
  28.    
  29.   cairo_move_to(cr, 20, 150);  
  30.   cairo_show_text(cr,"Who knows how to love you without being told");  
  31.   cairo_move_to(cr, 20, 180);  
  32.   cairo_show_text(cr,"Somebody tell me why I'm on my own");  
  33.   cairo_move_to(cr, 20, 210);  
  34.   cairo_show_text(cr,"If there's a soulmate for everyone");  
  35.    
  36.   cairo_destroy(cr);  
  37.    
  38.   returnFALSE;  
  39. }  
  40.    
  41.    
  42. int main (int argc,char*argv[])  
  43. {  
  44.   GtkWidget *window;  
  45.    
  46.   gtk_init(&argc, &argv);  
  47.    
  48.   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);  
  49.    
  50.   g_signal_connect(window,"expose-event",  
  51.       G_CALLBACK(on_expose_event), NULL);  
  52.   g_signal_connect(window,"destroy",  
  53.       G_CALLBACK(gtk_main_quit), NULL);  
  54.    
  55.   gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);  
  56.   gtk_window_set_default_size(GTK_WINDOW(window), 420, 250);  
  57.   gtk_window_set_title(GTK_WINDOW(window),"Soulmate");  
  58.   gtk_widget_set_app_paintable(window, TRUE);  
  59.    
  60.   gtk_widget_show_all(window);  
  61.    
  62.   gtk_main();  
  63.    
  64.   return0;  
  65. }  

在这个示例中,显示了 Natasha Bedingfield 的《灵魂伙伴》的部分歌词。(在这里,可以听这首歌,很美妙)

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

这里设置字体。这个函数接受了三个字体参数的传入,字体的名称、样式与轻重。


cairo_set_font_size(cr, 13);

这里设定字号。


cairo_move_to(cr, 20, 30);
cairo_show_text(cr,"Most relationships seem so transitory");

 通过在窗口中指定位置并调用 cairo_show_text() 函数显示文本。

 

 

一个字接一个字……

这种效果就是一个字一个字的显示,这些字的绘制存有时间差。


[html] view plaincopyprint?
  1. #include <cairo.h>  
  2. #include <gtk/gtk.h>  
  3.    
  4. gpointer text[7] = {"Z","e","t","C","o","d","e"};  
  5. gboolean timer = TRUE;  
  6.    
  7.    
  8. staticgboolean  
  9. on_expose_event(GtkWidget *widget,  
  10.     GdkEventExpose *event,  
  11.     gpointer data)  
  12. {  
  13.   cairo_t *cr;  
  14.   cairo_text_extents_t extents;  
  15.   staticgint 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.   returnFALSE;  
  46. }  
  47.    
  48. staticgboolean  
  49. time_handler (GtkWidget *widget)  
  50. {  
  51.   if(widget->window == NULL)returnFALSE;  
  52.    
  53.   if(!timer)returnFALSE;  
  54.    
  55.   gtk_widget_queue_draw(widget);  
  56.   returnTRUE;  
  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.   return0;  
  86. }  


在这个示例中,我们在 GTK+ 窗口中画了“ZetCode”这个字串,并让逐个字母伴随一定的时间差逐一显示。


gpointer text[7] = {"Z","e","t","C","o","d","e"};

构造一个字符数组。


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

将字体设置为 Courier。


for (i = 0; i < count; i++) {
   cairo_text_extents(cr, text[i], &extents);
   x += extents.width + 2;
   cairo_move_to(cr, x + 30, 50);
   cairo_show_text(cr, text[i]); 
}

开始逐个字的绘制。extents.width 给出了当前字符的宽度。

 

膨胀

下面这个示例中,我们制造了一种膨胀的效果。这个示例显示了一串在膨胀的居中文本,并且伴有淡出现象。这是很常见的效果,在 flash 动画里经常见到。


[html] view plaincopyprint?
  1. #include <cairo.h>  
  2. #include <gtk/gtk.h>  
  3.    
  4.    
  5. gpointer text[7] = {"Z","e","t","C","o","d","e"};  
  6. gboolean timer = TRUE;  
  7.    
  8.    
  9. staticgboolean  
  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.   staticgdouble alpha = 1.0;  
  18.   staticgdouble 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.   returnFALSE;  
  57. }  
  58.    
  59. staticgboolean  
  60. time_handler (GtkWidget *widget)  
  61. {  
  62.   if(widget->window == NULL)returnFALSE;  
  63.    
  64.   if(!timer)returnFALSE;  
  65.    
  66.   gtk_widget_queue_draw(widget);  
  67.    
  68.   returnTRUE;  
  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.   return0;  
  97. }  


这个示例在 GTK+ 窗口中制造了一种膨胀并且淡出的文本渲染效果。


gint x = widget->allocation.width / 2;
gint y = widget->allocation.height / 2;

获取窗口中心坐标。


cairo_set_source_rgb(cr, 0.5, 0, 0);
cairo_paint(cr);

将背景设为暗红色。


size += 0.8;

每轮循环,字号都增长 0.8 个单位。


if (size > 20) {
    alpha -= 0.01;
}

当字号大于 20 的时候,就开始淡出。


cairo_text_extents(cr,"ZetCode", &extents);

获取文本尺寸。


cairo_move_to(cr, x - extents.width/2, y);

根据文本尺寸来将文本定位在窗口的中心位置。


cairo_text_path(cr,"ZetCode");
cairo_clip(cr);

获取文本的的路径,并将其设为当前的裁剪域。


cairo_stroke(cr);
cairo_paint_with_alpha(cr, alpha);

绘制当前的路径,并为之添加 alpha 值(可实现淡出效果)。


转自    http://blog.csdn.net/haiwil/article/details/6771755


原创粉丝点击