首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

XCB 程式設計教學(四):視窗繪製文字與核心字體系統探討

     編輯:關於C++

前言

承接前三篇(建立視窗、繪圖、事件處理),本篇示範在 X 視窗繪製文字,並探討 X Server 核心字體系統與 Xft 的差異。

完整程式碼


#include <stdlib.h> #include <stdio.h> #include <string.h>
#include <inttypes.h> #include <xcb/xcb.h>

#define WIDTH 600 #define HEIGHT 400
#define TEST_COOKIE(fn, errMsg) \
    cookie = fn; \
    error = xcb_request_check(connection, cookie); \
    if (error) { fprintf(stderr, "Error: %s : %" PRIu8 "\n", errMsg, error->error_code); }

static void drawText(xcb_connection_t *conn, xcb_screen_t *screen, xcb_window_t win,
                     int16_t x, int16_t y, const char *font_name, const char *str) {
    xcb_void_cookie_t cookie; xcb_generic_error_t *error;
    xcb_font_t font = xcb_generate_id(conn);
    TEST_COOKIE(xcb_open_font_checked(conn, font, strlen(font_name), font_name), "Can't open font");
    xcb_gcontext_t gc = xcb_generate_id(conn);
    uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
    uint32_t values[3] = {screen->black_pixel, screen->white_pixel, font};
    TEST_COOKIE(xcb_create_gc_checked(conn, gc, win, mask, values), "Can't create GC");
    TEST_COOKIE(xcb_image_text_8_checked(conn, strlen(str), win, gc, x, y, str), "Can't draw text");
    xcb_close_font(conn, font); xcb_free_gc(conn, gc);
}

int main() {
    xcb_connection_t *conn = xcb_connect(NULL, NULL);
    xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;

    xcb_window_t win = xcb_generate_id(conn);
    uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
    uint32_t vals[2] = {screen->white_pixel,
        XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS |
        XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_POINTER_MOTION};
    xcb_create_window(conn, screen->root_depth, win, screen->root, 20, 200,
                      WIDTH, HEIGHT, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
                      screen->root_visual, mask, vals);
    xcb_map_window(conn, win); xcb_flush(conn);

    xcb_generic_event_t *ev;
    while ((ev = xcb_wait_for_event(conn))) {
        switch (ev->response_type & ~0x80) {
            case XCB_EXPOSE:
                drawText(conn, screen, win, 10, 20, "fixed", "Press ESC key to exit.");
                drawText(conn, screen, win, 10, 40, "Dejavu Sans Mono", "Press ESC key to exit.");
                drawText(conn, screen, win, 10, 60, "文泉驛正黑", "按ESC鍵退出。");
                break;
            case XCB_KEY_RELEASE: {
                xcb_key_release_event_t *kr = (xcb_key_release_event_t*)ev;
                if (kr->detail == 9) { free(ev); xcb_disconnect(conn); return 0; }
            }
        }
        free(ev);
    }
    return 0;
}

執行結果

僅 fixed 字體成功繪製,其餘字體報錯「無法開啟字體」。

核心字體系統 vs Xft

  • XCB 僅支援 X Server 核心字體系統 安裝的字體(xlsfonts 列出)。
  • 核心字體系統字體名稱冗長(如 -misc-fixed-medium-r-normal--13-120-75-75-c-70-iso10646-1),安裝需 mkfontdir、mkfontscale 等繁瑣步驟。
  • Xorg 官方不建議使用核心字體系統,推薦 Xft(FreeType + Fontconfig),支援現代字體格式、反鋸齒、複雜文字佈局。
  • 高層工具包已全面採用 Xft/Pango/HarfBuzz,XCB 僅適合學習 X 協定底層機制。

關鍵 API 流程

  1. xcb_generate_id() 產生字體 ID
  2. xcb_open_font_checked() 開啟字體
  3. 建立 GC 時 mask 包含 XCB_GC_FONT,values 填入 font ID
  4. xcb_image_text_8_checked() 繪製 8-bit 文字(另有 _16/_32 版本支援 UTF-16/32)
  5. 用畢 xcb_close_font()、xcb_free_gc() 釋放資源

錯誤檢查巨集

程式開頭定義 TEST_COOKIE 巨集,簡化 _checked 版本函式的 Cookie 檢查流程,提升可讀性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved