|
Packit |
324a5c |
...-----=======-----...
|
|
Packit |
324a5c |
Cairo 1.0 Porting Guide
|
|
Packit |
324a5c |
...-----=======-----...
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Here are some notes on more easily porting cairo_code from cairo 0.4
|
|
Packit |
324a5c |
to cairo 1.0. It is sorted roughly in order of importance, (the items
|
|
Packit |
324a5c |
near the top are expected to affect the most people).
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Automated API renamings
|
|
Packit |
324a5c |
=======================
|
|
Packit |
324a5c |
There have been a lot of simple renamings where the functionality is
|
|
Packit |
324a5c |
the same but the name of the symbol is different. We have provided a
|
|
Packit |
324a5c |
script to automate the conversion of these symbols. It can be found
|
|
Packit |
324a5c |
within the cairo distribution in:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
util/cairo-api-update
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
This script is used by installing it somewhere on your PATH, and the
|
|
Packit |
324a5c |
running it and providing the names of your source files on the command
|
|
Packit |
324a5c |
line. For example:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
cairo-api-update *.[ch]
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
The script will first save backup copies of each file (renamed with a
|
|
Packit |
324a5c |
.bak extension) and then will perform all of the simple renamings.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
For your benefit, the script also produces messages giving filenames
|
|
Packit |
324a5c |
and line numbers for several of the manual API updates that you will
|
|
Packit |
324a5c |
need to perform as described below.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Manual API changes
|
|
Packit |
324a5c |
==================
|
|
Packit |
324a5c |
This section of the porting guide describes changes you will have to
|
|
Packit |
324a5c |
manually make to your source code. In addition to the information in
|
|
Packit |
324a5c |
this guide, the cairo-api-update script will notify you of some of
|
|
Packit |
324a5c |
these issues as described above.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Cairo's deprecation warnings
|
|
Packit |
324a5c |
----------------------------
|
|
Packit |
324a5c |
Also, if your compiler provides warnings for implicit declarations of
|
|
Packit |
324a5c |
functions, (eg. "gcc -Wall"), then simply attempting to compile your
|
|
Packit |
324a5c |
program will cause cairo to generate messages intended to guide you
|
|
Packit |
324a5c |
through the porting process.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
For example, if you neglect to update an old call to
|
|
Packit |
324a5c |
cairo_set_target_drawable, you might see an error message as follows:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
foo.c:10: warning: implicit declaration of function
|
|
Packit |
324a5c |
‘cairo_set_target_drawable_DEPRECATED_BY_cairo_xlib_surface_create’
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
This message is indicating to you that the deprecatd function
|
|
Packit |
324a5c |
cairo_set_target_drawable appears in your program foo.c on line 10,
|
|
Packit |
324a5c |
and you should rewrite your program to call cairo_xlib_surface_create
|
|
Packit |
324a5c |
instead.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
The remainder of this porting guide is arranged as a set of common
|
|
Packit |
324a5c |
code patterns that appear in old (cairo-0.4) code and how it should be
|
|
Packit |
324a5c |
transformed to new (cairo-0.5) code.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
cairo_create
|
|
Packit |
324a5c |
------------
|
|
Packit |
324a5c |
Was: cr = cairo_create ();
|
|
Packit |
324a5c |
cairo_set_target_foo (cr, args);
|
|
Packit |
324a5c |
/* draw */
|
|
Packit |
324a5c |
cairo_destroy (cr);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Now: cairo_surface_t *surface;
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
surface = cairo_foo_surface_create (args);
|
|
Packit |
324a5c |
cr = cairo_create (surface);
|
|
Packit |
324a5c |
/* draw */
|
|
Packit |
324a5c |
cairo_destroy (cr);
|
|
Packit |
324a5c |
cairo_surface_destroy (surface);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Or: cairo_surface_t *surface;
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
surface = cairo_foo_surface_create (args);
|
|
Packit |
324a5c |
cr = cairo_create (surface);
|
|
Packit |
324a5c |
cairo_surface_destroy (surface);
|
|
Packit |
324a5c |
/* draw */
|
|
Packit |
324a5c |
cairo_destroy (cr);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
NOTE: Many of the cairo_foo_surface_create functions accept the
|
|
Packit |
324a5c |
identical arguments as the the old cairo_set_target_foo
|
|
Packit |
324a5c |
functions, (minus the cairo_t*), making this transformation
|
|
Packit |
324a5c |
quite easy. One notable exception is cairo_set_target_drawable
|
|
Packit |
324a5c |
which, when it becomes cairo_xlib_surface_create must pickup new
|
|
Packit |
324a5c |
arguments for the Visual*, the width, and the height.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
cairo_set_alpha (1)
|
|
Packit |
324a5c |
-------------------
|
|
Packit |
324a5c |
Was: cairo_set_rgb_color (cr, red, green, blue);
|
|
Packit |
324a5c |
cairo_set_alpha (cr, alpha);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Now: cairo_set_source_rgba (cr, red, green, blue, alpha);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
cairo_show_surface
|
|
Packit |
324a5c |
------------------
|
|
Packit |
324a5c |
Was: cairo_show_surface (cr, surface, width, height);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Now: cairo_set_source_surface (cr, surface, x, y);
|
|
Packit |
324a5c |
cairo_paint (cr);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
NOTE: The type signatures of cairo_show_surface and cairo_set_source
|
|
Packit |
324a5c |
are the same, but pay attention that cairo_show_surface required
|
|
Packit |
324a5c |
the width and height, while cairo_set_source_surface requires
|
|
Packit |
324a5c |
the X,Y location to where the surface will be placed.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
cairo_set_alpha (2)
|
|
Packit |
324a5c |
-------------------
|
|
Packit |
324a5c |
Was: cairo_set_alpha (cr, alpha);
|
|
Packit |
324a5c |
cairo_show_surface (cr, surface, width, height);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Now: cairo_set_source_surface (cr, surface, x, y);
|
|
Packit |
324a5c |
cairo_paint_with_alpha (cr, alpha);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
filling and stroking
|
|
Packit |
324a5c |
--------------------
|
|
Packit |
324a5c |
Was: cairo_save (cr);
|
|
Packit |
324a5c |
/* set fill color */
|
|
Packit |
324a5c |
cairo_fiill (cr);
|
|
Packit |
324a5c |
cairo_restore (cr);
|
|
Packit |
324a5c |
/* set stroke color */
|
|
Packit |
324a5c |
cairo_stroke (cr);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Now: /* set fill color */
|
|
Packit |
324a5c |
cairo_fill_preserve (cr);
|
|
Packit |
324a5c |
/* set stroke color */
|
|
Packit |
324a5c |
cairo_stroke (cr);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
NOTE: The current path is no longer saved/restored by
|
|
Packit |
324a5c |
cairo_save/cairo_restore. This can lead to some subtle
|
|
Packit |
324a5c |
surprises, so look out.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
cairo_matrix_t
|
|
Packit |
324a5c |
--------------
|
|
Packit |
324a5c |
Was: cairo_matrix_t *matrix;
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
matrix = cairo_matrix_create ();
|
|
Packit |
324a5c |
/* Do stuff with matrix */
|
|
Packit |
324a5c |
cairo_matrix_destroy (matrix);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Now: cairo_matrix_t matrix;
|
|
Packit |
324a5c |
cairo_matrix_init_identity (&matrix);
|
|
Packit |
324a5c |
/* Do stuff with &matrix */
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
NOTE: If you are really lazy, you can still use a cairo_matrix_t* and
|
|
Packit |
324a5c |
avoid putting the &matrix all over by just replacing
|
|
Packit |
324a5c |
cairo_matrix_create() with malloc() and cairo_matrix_destroy()
|
|
Packit |
324a5c |
with free(). That's not as nice, and you still need to be
|
|
Packit |
324a5c |
careful to see if you need to initialize it to an identity
|
|
Packit |
324a5c |
matrix as cairo_matrix_create() did for you.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Rendering to a temporary surface
|
|
Packit |
324a5c |
--------------------------------
|
|
Packit |
324a5c |
Was: cairo_save (cr);
|
|
Packit |
324a5c |
{
|
|
Packit |
324a5c |
cairo_set_target_surface (cr, temporary);
|
|
Packit |
324a5c |
/* draw through cr onto temporary */
|
|
Packit |
324a5c |
}
|
|
Packit |
324a5c |
cairo_restore (cr);
|
|
Packit |
324a5c |
/* use temporary as source on cr */
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Now: {
|
|
Packit |
324a5c |
cr2 = cairo_create (temporary);
|
|
Packit |
324a5c |
/* draw through cr2 onto temporary */
|
|
Packit |
324a5c |
cairo_destory (cr2);
|
|
Packit |
324a5c |
}
|
|
Packit |
324a5c |
/* use temporary as source on cr */
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
NOTE: Having to create another cairo_t is a bit annoying, but having
|
|
Packit |
324a5c |
to invent a new name for it is just awful, (imagine a deeply
|
|
Packit |
324a5c |
nested version of this code). Fortunately, the style above is
|
|
Packit |
324a5c |
just a stop-gap measure until the new group API comes along.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Iterating over a path
|
|
Packit |
324a5c |
---------------------
|
|
Packit |
324a5c |
Was: cairo_current_path (cr,
|
|
Packit |
324a5c |
my_move_to,
|
|
Packit |
324a5c |
my_line_to,
|
|
Packit |
324a5c |
my_curve_to,
|
|
Packit |
324a5c |
my_close_path,
|
|
Packit |
324a5c |
closure);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Now: int i;
|
|
Packit |
324a5c |
cairo_path_t *path;
|
|
Packit |
324a5c |
cairo_path_data_t *data;
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
path = cairo_copy_path (cr);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
for (i=0; i < path->num_data; i += path->data[i].header.length) {
|
|
Packit |
324a5c |
data = &path->data[i];
|
|
Packit |
324a5c |
switch (data->header.type) {
|
|
Packit |
324a5c |
case CAIRO_PATH_MOVE_TO:
|
|
Packit |
324a5c |
my_move_to (closure, data[1].point.x, data[1].point.y);
|
|
Packit |
324a5c |
break;
|
|
Packit |
324a5c |
case CAIRO_PATH_LINE_TO:
|
|
Packit |
324a5c |
my_line_to (closure, data[1].point.x, data[1].point.y);
|
|
Packit |
324a5c |
break;
|
|
Packit |
324a5c |
case CAIRO_PATH_CURVE_TO:
|
|
Packit |
324a5c |
my_curve_to (closure, data[1].point.x, data[1].point.y,
|
|
Packit |
324a5c |
data[2].point.x, data[2].point.y,
|
|
Packit |
324a5c |
data[3].point.x, data[3].point.y);
|
|
Packit |
324a5c |
break;
|
|
Packit |
324a5c |
case CAIRO_PATH_CLOSE_PATH:
|
|
Packit |
324a5c |
my_close_path (closure);
|
|
Packit |
324a5c |
break;
|
|
Packit |
324a5c |
}
|
|
Packit |
324a5c |
}
|
|
Packit |
324a5c |
cairo_path_destroy (path);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
NOTE: This version makes it looks like the new form is a _lot_ more
|
|
Packit |
324a5c |
verbose than the old version. But realize that the old version
|
|
Packit |
324a5c |
required the support of 4 additional functions. The new approach
|
|
Packit |
324a5c |
allows great flexibility including the ability to inline the
|
|
Packit |
324a5c |
entire operation within the switch statement when appropriate.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Erasing a surface to transparent
|
|
Packit |
324a5c |
--------------------------------
|
|
Packit |
324a5c |
Was: cairo_set_rgb_color (cr, 0., 0., 0.);
|
|
Packit |
324a5c |
cairo_set_alpha (cr, 0.)
|
|
Packit |
324a5c |
cairo_set_operator (cr, CAIRO_OPERATOR_SRC);
|
|
Packit |
324a5c |
cairo_rectangle (cr, 0., 0., surface_width, surface_height);
|
|
Packit |
324a5c |
cairo_fill (cr);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
or: cairo_set_rgb_color (cr, 0., 0., 0.);
|
|
Packit |
324a5c |
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
|
|
Packit |
324a5c |
cairo_rectangle (cr, 0., 0., surface_width, surface_height);
|
|
Packit |
324a5c |
cairo_fill (cr);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Now: cairo_set_source_rgba (cr, 0., 0., 0., 0.);
|
|
Packit |
324a5c |
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
|
Packit |
324a5c |
cairo_paint (cr);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
or: cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
|
|
Packit |
324a5c |
cairo_paint (cr);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
NOTE: Using cairo_rectangle and fill would still work just fine. It's
|
|
Packit |
324a5c |
just a lot more convenient to use cairo_paint now, (particularly
|
|
Packit |
324a5c |
as it doesn't require you to even know what the bounds of the
|
|
Packit |
324a5c |
target surface are).
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Drawing to a PNG file
|
|
Packit |
324a5c |
---------------------
|
|
Packit |
324a5c |
Was: file = fopen (filename, "w");
|
|
Packit |
324a5c |
cr = cairo_create ();
|
|
Packit |
324a5c |
cairo_set_target_png (cr, file, format, width, height);
|
|
Packit |
324a5c |
/* draw image */
|
|
Packit |
324a5c |
cairo_destroy (cr);
|
|
Packit |
324a5c |
fclose (file);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Now: surface = cairo_image_surface_create (format, width, height);
|
|
Packit |
324a5c |
cr = cairo_create (surface);
|
|
Packit |
324a5c |
/* draw image */
|
|
Packit |
324a5c |
cairo_surface_write_to_png (surface, filename);
|
|
Packit |
324a5c |
cairo_destroy (cr);
|
|
Packit |
324a5c |
cairo_surface_destroy (surface);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
NOTE: The png backend is gone. So there is no cairo_png_surface_create
|
|
Packit |
324a5c |
to take the place of cairo_set_target_png. And notice that we
|
|
Packit |
324a5c |
used an image surface here, but it is just as easy to use
|
|
Packit |
324a5c |
cairo_surface_write_to_png with an xlib or other surface, (but
|
|
Packit |
324a5c |
not PDF at the moment). This is one of the big advantages of
|
|
Packit |
324a5c |
this approach as opposed to a PNG surface.
|