jpayne@68: jpayne@68: jpayne@68:
jpayne@68: jpayne@68:jpayne@68: | ![]() |
jpayne@68: ![]() |
jpayne@68: ![]() |
jpayne@68: ![]() |
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: 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: