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