最小化重绘图以显示大图形

时间:2016-03-06 17:04:44

标签: c++ performance graphics cairo

我正在开发用于可视化图算法的软件。图形可以变得非常大(数万个节点)。在这种情况下,绘制图形的当前状态很慢。现在,绘图代码的格式为:

cairo_push_group(cr);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_paint(cr);
... // drawing vertices and edges with styles 
    // corresponding to the current stage of the algorithm
cairo_stroke(cr);
cairo_pop_group_to_source(cr);
cairo_paint(cr);
cairo_surface_flush(surface);
XFlush(d);

我正在努力的功能是拖动图表,用户可以点击任意点并拖动整个图表。重新绘制(即上述代码中的“......”部分)根本无法跟上。

问题是:有没有办法让转换矩阵的变化(即cairo_translate的应用)反映在屏幕上而不重新绘制?

我编写了以下小型完整程序来试验这个,但是我没有成功地产生积极的结果。这在main()

的评论中有说明
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cairo-xlib.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <unistd.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 *scr;

    screen = DefaultScreen(d);
    scr = DefaultScreenOfDisplay(d);
    if (!*x || !*y) {
       *x = WidthOfScreen(scr)/2; *y = HeightOfScreen(scr)/2;
       da = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, *x, *y, 0, 0,
                                0);
       //fullscreen (d, da);
    }
    else
        da =
            XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, *x, *y, 0, 0, 0);
    XSelectInput(d, da, ButtonPressMask | ButtonReleaseMask | KeyPressMask | ButtonMotionMask | StructureNotifyMask);
    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;
    }
    int x=500, y=500;
    cairo_surface_t* surface = create_x11_surface(d, &x, &y);
    cairo_t* cr = cairo_create(surface);
    char *text = argv[1];
    size_t text_len = 0;
    XEvent e;

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

    int last_delta_x = 0, last_delta_y = 0;
    int drag_start_x, drag_start_y;
    bool firstDraw = true;
    while(1)
    {

        if (XPending(cairo_xlib_surface_get_display(surface))) {
            XNextEvent(cairo_xlib_surface_get_display(surface), &e);
            switch(e.type) {
            case ButtonPress:
                drag_start_x = e.xbutton.x; drag_start_y = e.xbutton.y;
                break;
            case ButtonRelease:
                last_delta_x = 0; last_delta_y = 0;
                break;
            case MotionNotify:
                cairo_translate(cr, e.xmotion.x - drag_start_x - last_delta_x,
                                e.xmotion.y - drag_start_y - last_delta_y);
                last_delta_x = e.xmotion.x - drag_start_x;
                last_delta_y = e.xmotion.y - drag_start_y;
                break;
            case ConfigureNotify:
                cairo_xlib_surface_set_size(surface, e.xconfigure.width, e.xconfigure.height);
                break;
            default:
                fprintf(stderr, "Dropping unhandled XEevent.type = %d.\n",
                        e.type);
            }

        }

        if (firstDraw) {
            cairo_push_group(cr);
            cairo_set_source_rgb(cr, 0, 0, 0);
            cairo_paint(cr);

            cairo_set_source_rgb(cr, 0, 1, 0);
            cairo_move_to(cr, 0, 0);
            cairo_line_to(cr, 256, 256);
            cairo_move_to(cr, 256, 0);
            cairo_line_to(cr, 0, 256);
            cairo_set_line_width(cr, 10.0);
            cairo_stroke(cr);
            cairo_pop_group_to_source(cr);
            // firstDraw = false;
            // If the above is uncommented, translation is not reflected
        }
        cairo_paint(cr);
        cairo_surface_flush(surface);
        XFlush(d);

        sleep(0.1);
    }

    cairo_destroy(cr);
    cairo_surface_destroy(surface);
    return 0;
}

0 个答案:

没有答案