为什么 xcb_poly_segment 不绘制到像素图?

问题描述 投票:0回答:1

我正在尝试制作一个简单的 xcb 程序来学习基础知识并希望在其他项目中使用它,但我遇到了一个奇怪的问题。创建像素图后,我可以使用 xcb_poly_fill_rectangle 函数绘制它,然后 xcb_copy_area 与 xcb_flush 一起使其显示在屏幕上。当无论我尝试什么都无法使 xcb_poly_segment 绘制一些线段时,问题就出现了。

我是新来的,所以对我应该提出的问题的任何建议或更正都会被接受。

这是代码(也许有一些关于该问题的额外不必要的代码):

#include <stdio.h>
#include <stdlib.h>
#include <xcb/xcb.h>
#include <xcb/xcb_image.h>

int main(void)
{
    /* Misc declarations */
    int screen_num;

    xcb_get_geometry_reply_t *window_size;
    
    xcb_generic_error_t **window_size_error;
    
    uint32_t mask;
    uint32_t values[3];
    /* Open the connection to the X server */
    xcb_connection_t *connection = xcb_connect(NULL, &screen_num);

    if (xcb_connection_has_error(connection)) {
        fprintf(stderr, "Error: connection failed");
        return 1;
    }

    /* Get the current screen */
    const xcb_setup_t *setup = xcb_get_setup(connection);
    xcb_screen_iterator_t iterator = xcb_setup_roots_iterator(setup);

    for (int i = 0; i < screen_num; ++i) {
        xcb_screen_next(&iterator);
    }

    xcb_screen_t *screen = iterator.data;

    /* Create white (foreground) graphic context */
    xcb_gcontext_t white = xcb_generate_id(connection);
    mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
    values[0] = screen->white_pixel; 
    values[1] = 0;

    xcb_create_gc(connection, white, screen->root, mask, values);

    /* Create text (foreground) graphic context */
    xcb_gcontext_t text = xcb_generate_id(connection);
    mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_GRAPHICS_EXPOSURES;
    values[0] = 0x00FF00FF; 
    values[1] = 0xFF00FF00; 
    values[2] = 0;

    xcb_create_gc(connection, text, screen->root, mask, values);

    /* Create black graphic context */ /* Eraseable */
    xcb_gcontext_t black = xcb_generate_id(connection);
    mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
    values[0] = screen->black_pixel; 
    values[1] = 0;

    xcb_create_gc(connection, black, screen->root, mask, values);

    /* Create a window */
    mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
    values[0] = screen->black_pixel; /* bg color */
    values[1] = XCB_EVENT_MASK_EXPOSURE;

    xcb_window_t window = xcb_generate_id(connection);
    xcb_create_window(connection,
                      XCB_COPY_FROM_PARENT,
                      window,
                      screen->root,
                      0, 0,
                      640, 360,
                      10, 
                      XCB_WINDOW_CLASS_INPUT_OUTPUT,
                      screen->root_visual,
                      mask, values);

    /* Map the window on the screen and flush*/
    xcb_map_window(connection, window);
    xcb_flush(connection);

    /* Eraseable */
    xcb_segment_t segments[] = {
        {50, 50, 100, 100},
        {50, 100, 100, 50},
    };

    xcb_rectangle_t rectangle = {
        0, 0,
        50, 50
    };

    xcb_pixmap_t pixmap = xcb_generate_id(connection);
    xcb_create_pixmap(connection, screen->root_depth, 
            pixmap, window, 16, 16);

    /* draw primitives */
    xcb_generic_event_t *event;
    xcb_expose_event_t *ex_event;
    while ((event = xcb_wait_for_event(connection))) {
            switch (event->response_type & ~0x80) {
            case XCB_EXPOSE:
                /* Eraseable */
                ex_event = (xcb_expose_event_t *) event;

                xcb_poly_fill_rectangle(connection, pixmap, white, 1, &rectangle);

                xcb_poly_segment(connection, pixmap, white, 2, segments);

                xcb_copy_area(connection, pixmap, window, white, 
                        ex_event->x, ex_event->y, 
                        ex_event->x, ex_event->y, 
                        ex_event->width, ex_event->height);


                /* Reflush */
                xcb_flush(connection);
                break;
            case XCB_KEY_PRESS: 
                /* TODO */
                break;
            default:
                break;
            } 
            free(event);
    }

    xcb_disconnect(connection);
 
    return 0;
}

我尝试将 xcb_poly_segment 的可绘制对象更改为窗口,并在复制像素图后调用该函数(因此它不会覆盖)并且工作正常,但我无法使用“文本”图形上下文和其他一些变体一样,但没用。

我还寻找了一种方法来了解多段函数通过 cookie 返回的任何错误。我想我搜索得不够努力。

非常感谢任何回应。

编辑:找到答案,但没有解释:(

出于我不知道的原因,xcb_flush 函数破坏了某些东西。通过玩弄窗户,我可以在短时间内看到这些片段,然后消失在存在的虚空中。我认为它试图快速刷新,或者刷新速度很慢,但我不知道。

还修复了像素图尺寸过小的问题(小于绘制矩形和线段所需的区域)。

c x11 xlib xorg xcb
1个回答
0
投票

我对您的程序进行了以下更改:

--- t.c.orig    2024-07-02 17:07:30.085952668 +0200
+++ t.c 2024-07-02 17:11:07.498782376 +0200
@@ -86,12 +86,16 @@ int main(void)
 
     xcb_rectangle_t rectangle = {
         0, 0,
-        50, 50
+        300, 300
     };
 
     xcb_pixmap_t pixmap = xcb_generate_id(connection);
     xcb_create_pixmap(connection, screen->root_depth, 
-            pixmap, window, 16, 16);
+            pixmap, window, 300, 300);
+
+    /* I moved this up here since it only draws to the pixmap and that one keeps its content */
+    xcb_poly_fill_rectangle(connection, pixmap, white, 1, &rectangle);
+    xcb_poly_segment(connection, pixmap, black, 2, segments);
 
     /* draw primitives */
     xcb_generic_event_t *event;
@@ -102,10 +106,6 @@ int main(void)
                 /* Eraseable */
                 ex_event = (xcb_expose_event_t *) event;
 
-                xcb_poly_fill_rectangle(connection, pixmap, white, 1, &rectangle);
-
-                xcb_poly_segment(connection, pixmap, white, 2, segments);
-
                 xcb_copy_area(connection, pixmap, window, white, 
                         ex_event->x, ex_event->y, 
                         ex_event->x, ex_event->y, 
  • 我将绘图移至主循环之前,因为像素图保留了其内容。无需重新绘制。
  • 我将像素图的大小更改为 300x300,以便它实际上足够大以包含您要绘制的线条
  • 我更改了矩形的大小以适合像素图的大小
  • 我更改了
    xcb_poly_segment()
    调用以使用
    black
    GC 而不是
    white
    GC。在白色上画白色没有明显的结果。

结果看起来像这样,我希望这是你所期望的:

visual result from running the program

© www.soinside.com 2019 - 2024. All rights reserved.