1
votes

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);

1
Why are you using operator ATOP instead of e.g. SOURCE or OVER? Is there transparency involved at all? (I think ATOP is equal to SOURCE which is equal to OVER without any alpha)Uli Schlachter
Desperation. I was trying a lot of different things. SOURCE was correct. I also needed to paint the tmp_surf white before using the xy_surface as the source.James '-'
Please consider adding a screenshot to make this clearer.unwind

1 Answers

4
votes

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.