PORTING_GUIDE   [plain text]


		    ...-----=======-----...
		    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.