c - 多线程、gtk3 和 cairo : drawing in a cairo surface

标签 c drawing cairo gtk3 gdk

我正在尝试从线程绘制到 cairo 图像表面,但出现断言错误:

gtk_mt: /build/buildd/cairo-1.10.2/src/cairo-surface.c:385: _cairo_surface_begin_modification: Assertion `! surface->finished' failed. Aborted (core dumped)

这是我的程序:

#include <stdlib.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <cairo.h>

#define IMAGE_WIDTH 320
#define IMAGE_HEIGHT 200

gpointer thread_func(gpointer data)
{
    int x, y;
    unsigned char rgb_r, rgb_g, rgb_b;
    GtkWidget *widget = (GtkWidget*)data;
    GdkWindow *window;
    cairo_t *cr;
    cairo_format_t format = CAIRO_FORMAT_ARGB32;
    cairo_surface_t *surface;
    unsigned char *image_data, *rgbptr;
    int width = IMAGE_WIDTH;
    int height = IMAGE_HEIGHT;
    int stride;

    gdk_threads_enter();
    stride = cairo_format_stride_for_width(format, width);
    image_data = malloc(stride * height);
    surface = cairo_image_surface_create_for_data(image_data, format, width, height, stride);
    window = gtk_widget_get_window(widget);
    cr = gdk_cairo_create(window);
    gdk_threads_leave();

    while(1)
    {
        rgb_r = random() & 0xff;
        rgb_g = random() & 0xff;
        rgb_b = random() & 0xff;

        for(y = 0; y < height; ++y)
        {
            rgbptr = &image_data[y * stride];
            if(!(random() & 0x3f))
            {
                rgb_r = random() & 0xff;
                rgb_g = random() & 0xff;
                rgb_b = random() & 0xff;
            }           

            for(x = 0; x < width; ++x)
            {
                *rgbptr++ = rgb_r; *rgbptr++ = rgb_g; *rgbptr++ = rgb_b;
                *rgbptr = 0xff;
            }
        }

        gdk_threads_enter();
        cairo_set_source_surface(cr, surface, 0, 0);
        cairo_paint(cr);
        gdk_threads_leave();
        sleep(2);
    }

    return( NULL );
}

int main(int argc, char **argv)
{
  GtkWidget *window;
  GtkWidget *darea;
  GThread *thread;
  GError *error = NULL;

  if(! g_thread_supported())
        g_thread_init(NULL);
  gdk_threads_init();

  gdk_threads_enter();
  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  darea = gtk_drawing_area_new();
  gtk_widget_set_size_request(darea, IMAGE_WIDTH, IMAGE_HEIGHT);
  gtk_container_add(GTK_CONTAINER (window), darea);
  gtk_widget_show_all (window);

    thread = g_thread_create(thread_func, (gpointer)darea, FALSE, &error);
    if(!thread)
    {
        g_print("Error: %s\n", error->message);
        return(-1);
    }

    gtk_main();
    gdk_threads_leave();

    return( 0 );
}

感谢任何帮助!

最佳答案

好吧,似乎不可能重用 surface 和 cr。我将这些调用移到循环的 gdk_threads_enter() 部分内,然后它就可以工作了。 (此外,还有一个错误,我通过执行 *rgbptr = 0xff 写入 A channel ,我忘记了 post-inc 指针。)

关于c - 多线程、gtk3 和 cairo : drawing in a cairo surface,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11668628/

相关文章:

c - 在 c 中将 bool 的结果打印为 'false' 或 'true' 的最佳方法?

c - 如何在 GCM 模式下使用 AES 链接 BCryptEncrypt 和 BCryptDecrypt 调用?

android - 绘图 Canvas FC

javascript - 如何控制我的圈子的位置?

Android 2.1 View 的 getDrawingCache() 方法总是返回 null

c# - 无法使用 Mono.Cairo

c - 这些函数类型定义是什么意思?

c - 从不同的子目录链接到库目标

gtk - 如何在子类 DrawingArea 小部件中绘制?

javascript - 如何在 Node.js 中使用图像切片?