gpt4 book ai didi

Cairo C 程序不会绘制到 x11 窗口

转载 作者:太空狗 更新时间:2023-10-29 12:01:39 24 4
gpt4 key购买 nike

我正在尝试使用 Cairo Linux 上的 C 图形库,用于制作非常轻量级的 x11 GUI。

在非常努力地跟随 woefully incomplete guide 之后cairo 给出了 x11,这是我得到的最好的:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <cairo.h>
#include <cairo-xlib.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/renderproto.h>

//This function should give us a new x11 surface to draw on.
cairo_surface_t* create_x11_surface(int x, int y)
{
Display* d;
Drawable da;
int screen;
cairo_surface_t* sfc;

if((d = XOpenDisplay(NULL)) == NULL)
{
printf("failed to open display\n");
exit(1);
}

screen = DefaultScreen(d);
da = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, x, y, 0, 0, 0);
XSelectInput(d, da, ButtonPressMask | KeyPressMask);
XMapWindow(d, da);

sfc = cairo_xlib_surface_create(d, da, DefaultVisual(d, screen), x, y);
cairo_xlib_surface_set_size(sfc, x, y);

return sfc;
}

int main(int argc, char** argv)
{
//create a new cairo surface in an x11 window as well as a cairo_t* to draw
//on the x11 window with.
cairo_surface_t* surface = create_x11_surface(300, 200);
cairo_t* cr = cairo_create(surface);

while(1)
{
//save the empty drawing for the next time through the loop.
cairo_push_group(cr);

//draw some text
cairo_select_font_face(cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size(cr, 32.0);
cairo_set_source_rgb(cr, 0, 0, 1.0);
cairo_move_to(cr, 10.0, 25.0);

if((argc == 2) && (strnlen(argv[1], 100) < 50))
cairo_show_text(cr, argv[1]);
else
cairo_show_text(cr, "usage: ./p1 <string>");

//put the drawn text onto the screen(?)
cairo_pop_group_to_source(cr);
cairo_paint(cr);
cairo_surface_flush(surface);

//pause for a little bit.
int c = getchar();

//change the text around so we can see the screen update.
for(int i = 0; i < strnlen(argv[1], 100); i++)
{
argv[1][i] = argv[1][i + 1];
}

if(c == 'q')
{
break;
}
}

cairo_surface_destroy(surface);
return 0;
}

在安装了 Cairo 的 Linux 系统上,可以编译

gcc -o myprog $(pkg-config --cflags --libs cairo x11) -std=gnu99 main.c

它应该用一个参数运行。

由于我完全不明白的原因,插入行

cairo_pop_group_to_source(cr);
cairo_paint(cr);
cairo_surface_write_to_png (surface, "hello.png"); //<--------- inserted
cairo_surface_flush(surface);

在屏幕上放一些东西,但是有两个问题:

  1. 我用这种方法绘制的文本是持久的,产生了一种涂抹效果。
  2. 我不想在我的程序和 x11 窗口之间使用一些 .png 文件。数据应该直接发送!

最佳答案

几个问题:

  • 在 X11 中,X11 服务器不会将您绘制的内容保存到窗口,而是向您的窗口发送一个 ExposeEvent 以告知它重绘。这意味着您会得到一个黑色窗口,因为您没有处理此事件。
  • getchar 只在换行后给你一些东西,所以只输入一些东西是没有帮助的。
  • libX11 缓冲内容,仅在您等待事件(或缓冲区填满)时将其发送到 X11 服务器。由于您从不等待事件,因此它永远不会刷新。明确调用 XFlush 会有所帮助。
  • 你推的群没用。摆脱它。
  • 将字符串向左移动一个方向的代码很容易超出字符串的末尾。您显然已经知道这一点,因为您使用 strnlen“修复”了它。

这里有一个更好的解决方案,但它仍然给你一个最初的黑色窗口,因为你在它被映射之前绘制它:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cairo-xlib.h>
#include <X11/Xlib.h>

//This function should give us a new x11 surface to draw on.
cairo_surface_t* create_x11_surface(Display *d, int x, int y)
{
Drawable da;
int screen;
cairo_surface_t* sfc;

screen = DefaultScreen(d);
da = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, x, y, 0, 0, 0);
XSelectInput(d, da, ButtonPressMask | KeyPressMask);
XMapWindow(d, da);

sfc = cairo_xlib_surface_create(d, da, DefaultVisual(d, screen), x, y);

return sfc;
}

int main(int argc, char** argv)
{
Display *d = XOpenDisplay(NULL);
if (d == NULL) {
fprintf(stderr, "Failed to open display\n");
return 1;
}
//create a new cairo surface in an x11 window as well as a cairo_t* to draw
//on the x11 window with.
cairo_surface_t* surface = create_x11_surface(d, 300, 200);
cairo_t* cr = cairo_create(surface);
char *text = argv[1];
size_t text_len = 0;

if (argc != 2)
text = NULL;
else
text_len = strlen(text);

while(1)
{
// Clear the background
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_paint(cr);

//draw some text
cairo_select_font_face(cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size(cr, 32.0);
cairo_set_source_rgb(cr, 0, 0, 1.0);
cairo_move_to(cr, 10.0, 25.0);

if (text)
cairo_show_text(cr, text);
else
cairo_show_text(cr, "usage: ./p1 <string>");

cairo_surface_flush(surface);
XFlush(d);

//pause for a little bit.
int c = getchar();

//change the text around so we can see the screen update.
memmove(text, &text[1], text_len);
if (text_len > 0)
text_len--;

printf("got char %c\n", c);
if(c == 'q')
{
break;
}
}

// XXX: Lots of other stuff isn't properly destroyed here
cairo_surface_destroy(surface);
return 0;
}

编辑:另外,为什么你觉得 cairo 只给你一个非常不完整的指南?它告诉你如何让 cairo 部分工作,它还解释了一些关于 X11 的部分,即使你应该已经知道那些如果你想使用 cairo-x11。那不关它的事。您链接到的指南甚至提供了一个完整的、有效的和独立的示例:https://www.cypherpunk.at/files/2014/11/cairo_xlib_simple.c

关于Cairo C 程序不会绘制到 x11 窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33385243/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com