Question

I have a program that gathers data which varies with time. I have displayed the data in real time using a program written in C with Gtk3. In a "render" function, data is drawn on an off screen surface, and later copied to a drawing area surface on an expose event.

This retains the surface from the previous render operation, and what I want to do is move the image to the left a step size, before drawing new data at the right side. The net effect should be an image that scrolls to the left with new data appearing at the right edge.

My attempts thus far have been to create a new surface, use the old surface as the source for the new, and paint it on with a shift, then use a similar few commands to paint the new surface back to the original, before adding new data.

It kinda works, but the image gets blurred as it moves further left, and the background white disappears.

Is there a way to keep it sharp and achieve what I'm trying to achieve?

BTW, I'm developing on GNU/Linux, but the program does build and run on Windows as well.

James.

    //Cairo context for the existing surface.
    cr = cairo_create (xy_surface);

    //create a similar surface to the existing surface
    cairo_surface_t *tmp_surf = cairo_surface_create_similar(xy_surface, 
         CAIRO_CONTENT_COLOR, width-2, height);

    //create cairo context for the new surface
    cairo_t *tmp_cr = cairo_create (tmp_surf);

    source_x = ((gdouble)width * N_SAMPLES / sweep_rate) - 2;
    dest_x = 0.0;

    //Set the drawing source for the new surface to be the old surface
    cairo_set_source_surface (tmp_cr, xy_surface, dest_x - source_x, 0.0);
    cairo_rectangle (tmp_cr, dest_x, 0, width - 2 - source_x, height);
    cairo_set_operator(tmp_cr, CAIRO_OPERATOR_SOURCE);
    cairo_fill (tmp_cr);
    cairo_destroy(tmp_cr);

    //clear the existing surface
    cairo_set_source_rgb(cr, 1, 1, 1);
    cairo_paint(cr);

    cairo_set_operator(cr, CAIRO_OPERATOR_ATOP);
    cairo_set_source_surface(cr, tmp_surf, 0, 0);
    cairo_paint(cr);

    cairo_surface_destroy(tmp_surf);

Was it helpful?

Solution

If width is uneven you well get a .5 value for the surface origin, which means that pixel left and right (roundup, rounddown) will get painted partially based on the colors of the pixel neighbors of your surface.

Simply make sure that the source_x has no decimal digits i.e. do rint (source_x) before using.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top