summaryrefslogtreecommitdiff
path: root/PORTING_GUIDE
blob: b8bdd37b64c9ae7c21dd6db8be47554d7c689cfd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
		    ...-----=======-----...
		    Cairo 0.5 Porting Guide
		    ...-----=======-----...

Here are some notes on more easily porting cairo_code from cairo 0.4
to cairo 0.5. 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);

Now:	cairo_set_source_rgba (cr, 0., 0., 0., 0.);
	cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
	cairo_paint (cr);

NOTE: Using cairo_rectanlgle 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.