jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: Streams and File I/O: Cairo: A Vector Graphics Library jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:
jpayne@68:

jpayne@68: Streams and File I/O

jpayne@68:

jpayne@68: Various places in the cairo API deal with reading and writing jpayne@68: data, whether from and to files, or to other sources and jpayne@68: destinations. In these cases, what is typically provided in the jpayne@68: C API is a simple version that just takes a filename, and a jpayne@68: complex version that takes a callback function. jpayne@68: An example is the PNG handling functions: jpayne@68:

jpayne@68:
jpayne@68: cairo_surface_t *
jpayne@68: cairo_image_surface_create_from_png (const char	*filename);
jpayne@68: 
jpayne@68: cairo_surface_t *
jpayne@68: cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func,
jpayne@68: 					    void             *closure);
jpayne@68: 
jpayne@68: cairo_status_t
jpayne@68: cairo_surface_write_to_png (cairo_surface_t	*surface,
jpayne@68: 			    const char		*filename);
jpayne@68: 
jpayne@68: cairo_status_t
jpayne@68: cairo_surface_write_to_png_stream (cairo_surface_t	*surface,
jpayne@68: 				   cairo_write_func_t	write_func,
jpayne@68: 				   void			*closure);
jpayne@68:

jpayne@68: The expectation is that the filename version will be mapped jpayne@68: literally in the language binding, but the callback version jpayne@68: will be mapped to a version that takes a language stream jpayne@68: object. For example, in Java, the four functions above jpayne@68: might be mapped to: jpayne@68:

jpayne@68:
jpayne@68: static public ImageSurface createFromPNG (String filename) throws IOException;
jpayne@68: static public ImageSurface createFromPNG (InputStream stream) throws IOException;
jpayne@68: public void writeToPNG (String filename) throws IOException;
jpayne@68: public void writeToPNG (OutputStream stream) throws IOException;
jpayne@68: 
jpayne@68:

jpayne@68: In many cases, it will be better to jpayne@68: implement the filename version internally jpayne@68: using the stream version, rather than building it on top of the jpayne@68: filename version in C. The reason for this is that will jpayne@68: naturally give a more standard handling of file errors for jpayne@68: the language, as seen in the above Java example, where jpayne@68: createFromPNG() is marked as raising jpayne@68: an exception. Propagating exceptions from inside the callback jpayne@68: function to the caller will pose a challenge to the language jpayne@68: binding implementor, since an exception must not propagate jpayne@68: through the Cairo code. A technique that will be useful in jpayne@68: some cases is to catch the exception in the callback, jpayne@68: store the exception object inside a structure pointed to by jpayne@68: closure, and then rethrow it once jpayne@68: the function returns. jpayne@68:

jpayne@68:

jpayne@68: I'm not sure how to handle this for jpayne@68: cairo_pdf_surface_create_for_stream(). jpayne@68: Other than keep a “exception to rethrow” thread-specific jpayne@68: variable jpayne@68: that is checked after every call to a Cairo jpayne@68: function. jpayne@68:

jpayne@68:
jpayne@68: jpayne@68: jpayne@68: