码迷,mamicode.com
首页 > Windows程序 > 详细

使用XCB编写X Window程序(04):在窗口中绘制文字

时间:2014-07-16 17:43:37      阅读:510      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   使用   文件   

   在前面的几节中,我展示了使用XCB创建窗口、在窗口中画图以及捕获并处理事件。在这一篇中,我将展示在窗口中绘制文字。绘制文字当然离不开字体,所以我还会简单地探讨一下X Server的核心字体系统。老规矩,先上代码和运行效果图,代码如下:

 1 #include <stdlib.h>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <inttypes.h>
 5 #include <xcb/xcb.h>
 6 
 7 
 8 #define    WIDTH 600
 9 #define    HEIGHT 400
10 #define TEST_COOKIE(fn,errMessage) 11     cookie=fn; 12     error=xcb_request_check(connection,cookie); 13     if(error){ 14         fprintf(stderr, "Error: %s : %"PRIu8"\n", errMessage, error->error_code); 15     } 16 
17 static void drawText(xcb_connection_t *connection, xcb_screen_t *screen, xcb_window_t window,
18         int16_t x, int16_t y, const char *font_name, const char *string){
19     /*cookie and error, for TEST_COOKIE */
20     xcb_void_cookie_t cookie;
21     xcb_generic_error_t *error;
22 
23     xcb_font_t font = xcb_generate_id(connection);
24     TEST_COOKIE(xcb_open_font_checked(connection, font, strlen(font_name), font_name), "Can‘t open font");
25     xcb_gcontext_t gc = xcb_generate_id(connection);
26     uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
27     uint32_t values[3] = {screen->black_pixel, screen->white_pixel, font};
28     TEST_COOKIE(xcb_create_gc_checked(connection, gc, window, mask, values), "Can‘t create GC")
29     /*draw the text*/
30     TEST_COOKIE(xcb_image_text_8_checked(connection, strlen(string), window, gc, x, y, string), "Can‘t draw text");
31     /*close the font*/
32     xcb_close_font(connection, font);
33     xcb_free_gc(connection, gc);
34 }
35 
36 int main()
37 {
38     xcb_connection_t *connection = xcb_connect(NULL, NULL);
39     xcb_screen_t *screen = xcb_setup_roots_iterator( xcb_get_setup(connection)).data;
40 
41     /*Create the window*/
42     xcb_window_t window = xcb_generate_id(connection);
43     uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
44     uint32_t values[2];
45     values[0] = screen->white_pixel;
46     values[1] = XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS |
47         XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_POINTER_MOTION;
48     xcb_create_window(connection, screen->root_depth,
49             window, screen->root, 20, 200,
50             WIDTH, HEIGHT,
51             0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
52             screen->root_visual,
53             mask, values);
54     xcb_map_window(connection, window);
55     xcb_flush(connection);
56 
57     /*event loop*/
58     xcb_generic_event_t *event;
59     while((event = xcb_wait_for_event(connection))){
60         switch(event->response_type & ~0x80){
61             case XCB_EXPOSE:
62                 {
63                     drawText(connection, screen, window, 10, 20,"fixed", "Press ESC key to exit.");
64                     drawText(connection, screen, window, 10, 40, "Dejavu Sans Mono", "Press ESC key to exit.");
65                     drawText(connection, screen, window, 10, 60, "文泉驿正黑", "按ESC键退出。");
66                     break;
67                 }
68             case XCB_KEY_RELEASE:
69                 {
70                     xcb_key_release_event_t *kr = (xcb_key_release_event_t*)event;
71                     switch(kr->detail){
72                         case 9: /* ESC */
73                             {
74                                 free(event);
75                                 xcb_disconnect(connection);
76                                 return 0;
77                             }
78                     }
79                 }
80         }
81         free(event);
82     }
83     return 0;
84 }

运行效果如下图:

bubuko.com,布布扣

 

  我承认,这段代码写得有点乱,不过说明怎么在窗口中绘制文字已经足够了。在窗口中绘制文字只需要用到如下函数:

  1、使用xcb_generate_id()生成一个ID,用来表示一个字体;

  2、使用xcb_open_font()或者xcb_open_font_checked()函数打开一个字体;

  3、使用前面打开的字体创建一个gc;创建gc前面已经讲过了,只需要调用xcb_generate_id()和xcb_create_gc()或者xcb_create_gc_checked()函数即可,不过在这里,要注意创建gc时的mask和values值,mask需要XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT,分别代表前景色、背景色和字体,在values中设置相应的值;

  4、使用xcb_image_text_8()或者xcb_image_text_8_checked()函数在窗口上绘制文字。

 

  现在再回过头来看代码,是不是觉得豁然开朗?就这么几个API而已。而且可以看出,在XCB中,每一个有可能出错的函数都有另外一个加上了_checked的版本,带_checked的版本会返回一个cookie,通过xcb_request_check()函数可以检查该cookie,从而判断该函数调用是否成功。使用C语言的API就是这一点很麻烦,经常要去检查函数调用是否成功,所以使用C语言写程序经常会写成这样:

int error;
error = some_function(...);
if(error){
    printf("...some message...");
    ...
}
error = another_function(...);
if(error){
    printf("....another message...");
    ...
}

  这实在是太痛苦了。好在C语言中还有宏这么一个东西,所以我就在程序的开头定义了一个宏TEST_COOKIE,专门用来干这个事。宏定义得不好,还有改进的余地,不过已经让我的代码写起来和读起来都舒服了不少。

  在程序中,我使用了三个drawText,要求程序分别用fixed字体、Dejavu San Mono字体和文泉驿正黑字体绘制三行文字,但是最终的结果只有fixed那一行成功绘制,剩下的两行都在控制台显示有错误信息,都表示字体打不开、gc创建不了、所以文字当然绘制不了。之所以出现这种情况,就是因为这里选择的字体只能是X Server核心字体系统里安装的字体。我在《Linux江湖05:Linux桌面系统字体配置要略(下)》里面写过,Xorg中有两种字体系统,一种是X Server核心字体系统,另一种是Xft。虽然X Server核心字体系统经过多年的发展,功能已经很完善了,能比较完美地支持TrueType字体,但是Xorg官方反复建议大家不要使用核心字体系统,而是推荐大家使用Xft。可能是因为X Server核心字体系统对字体的安装和管理都比较麻烦吧。使用xlsfonts命令可以列出X Server中安装有哪些字体,如下图:

bubuko.com,布布扣

  可以看到每一个字体的信息都又臭又长,只有最后三行短一点,所以我才在程序中选择了最短的fixed字体作为示例。而且X Server核心字体系统安装字体时需要使用mkfontdir、mkfontscale等极其麻烦的命令。

  最后有一点想不通的是,为什么xcb_image_text_8()函数后面有一个8呢?是不是还有xcb_image_text_16()和xcb_image_text_32()这样的函数呢?没关系,使用Ctrl+]跳到XCB的头文件里面看一下。如下图:

bubuko.com,布布扣

  里面的注释还是很详细的。特别是下图的最后一句:

bubuko.com,布布扣

最后一句再次强调X core fonts是过时的、不建议使用的,再次推荐大家使用Xft。我在写这一系列XCB文章的时候就说过,使用XCB只是为了学习,学习X协议的底层知识,学习GUI系统的构建原理等。真正写应用程序的时候,是没有谁使用XCB这么底层的库的。而高层次的库中需要绘制文字时,估计早就都是Xft一统天下了,所以并不需要我们费太多的心。

 

(京山游侠于2014-07-15发布于博客园,转载请注明出处。)

使用XCB编写X Window程序(04):在窗口中绘制文字,布布扣,bubuko.com

使用XCB编写X Window程序(04):在窗口中绘制文字

标签:style   blog   http   color   使用   文件   

原文地址:http://www.cnblogs.com/youxia/p/gui004.html

(1)
(1)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!