[cairo] cairo_copy / cairo_rectangle

Carl Worth cworth at cworth.org
Thu Sep 10 17:55:38 PDT 2009


Excerpts from Lars Fomsgaard's message of Thu Sep 10 11:17:07 -0700 2009:
> Hi

Hi Lars!

> I am trying to make a program (gtk) for displaying some waveforms,
> where i would like to use cairo for the drawing. I was hoping, that i
> could start by drawing the waveforms to one big surface and then use
> funtions like cairo_scale and cairo_rectangle to handle things like
> zooming and redrawing when the window has been hidden.

You can do things like that. You may or may not be pleased with the
result of doing cairo_scale with a source surface like this,
though. That is, if you draw the original surface at one scale, and
then cairo_paint() it to another surface with scaling, then you will
be rescaling a rasterized version of your waveform. The results will
generally be much better if you avoid scaling a raster image by
instead always drawing at the desired scale.

That is, you may want to redraw your backing surface when the desired
zoom changes.

So that's something to keep in mind.

> My problem is that when i draw directly to the "cairo_t", that is
> connected to the window, the waves display nicely, but when i draw to
> my backup surface and use cairo_copy i end up with a blanc window.
> Does anyone have a piece of advise for a cairo-beginner. I have pasted
> in a small testprogram below.

Thanks for the small test program. That makes it really easy to find
the problem.

And the problem has to do with you passing an invalid value to a cairo
function. The way cairo deals with an error like this is that once an
error occurs on a cairo object, (such as a cairo_surface_t or a
cairo_t), that object shuts down and will no longer do anything. Using
an in-error object with another object causes the original error to
then propagate to the next object which will also shut down, etc.

There are at least two important reasons for scheme:

1. It's very hard for errors to go undetected. (The propagation and
   lack of drawing almost guarantee you'll notice if something has
   gone wrong.)

2. You can write a correct program without having to check for error
   return values after every cairo call. Instead, you can check for an
   error when convenient, (such as at the end of your expose event),
   and still be sure that the calls between the error and the error
   check won't result in any crashes.

So, I added the following call to the end of your program, just before
the cairo_destroy[*] at the end of expose:

  if (cairo_status (disp_cr))
      printf ("Cairo is unhappy: %s\n",
              cairo_status_to_string (cairo_status (disp_cr)));

And I saw the following error:

  Cairo is unhappy: invalid value for an input cairo_content_t

That's perhaps not extremely elucidating, but it is something. Another
step you can do is to run your program in a debugger and break on
_cairo_error. That will let you find the first cairo call you make
that triggers an error.

In this case, you can scan your program for a cairo call that accepts
a cairo_content_t. Here is where it is:

>     draw_surface=cairo_surface_create_similar(
>         cairo_get_target(disp_cr),
>         cairo_surface_get_type(cairo_get_target(disp_cr)),
>         300,
>         200);

The problem here is in the second argument to
cairo_surface_create_similar. It wants a cairo_content_t, but you're
instead passing a cairo_surface_type_t which is not the same thing at
all.

Instead, with cairo_content_t you can express whether the surface
should have transparency, (that is color and alpha), or not (just
color), or even just alpha.

Assuming you might want some transparency, you can use:

    draw_surface=cairo_surface_create_similar(
        cairo_get_target(disp_cr),
        CAIRO_CONTENT_COLOR_ALPHA,
        300,
        200);

Now cairo should be much happier.

>   cairo_set_source_surface(disp_cr, cairo_get_target(draw_cr), 0, 0);
>   /*cairo_rectangle (disp_cr, 50, 50, 200, 100);
>   cairo_fill (disp_cr);*/
>   cairo_paint(disp_cr);
>   cairo_stroke(disp_cr);

Wow. That's a lot of attempts at drawing. :-)

You don't want either the cairo_fill nor the cairo_stroke here, (they
won't actually do anything since you don't have any path---but if you
put the cairo_rectangle call back, then cairo_fill would fill that
rectangle with your source surface). You probably want just the
cairo_paint call here.

I hope that helps. And have fun with cairo!

-Carl
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.cairographics.org/archives/cairo/attachments/20090910/1a51909a/attachment.pgp 


More information about the cairo mailing list