[cairo] API Shakeup: cairo_output_stream_t and cairo_surface_finish()

Kristian Høgsberg krh at bitplanet.net
Mon Feb 21 17:52:26 PST 2005


Kristian Høgsberg wrote:
> Hi,
> 
> Here is a proposal for an output stream abstraction to be used for
> cairo's output stream needs.  We add a new object, 
> cairo_output_stream_t, to the user API:

And here's a first stab at the implementation.  I decided to go with the
API that keeps the cairo_output_stream_t out of the public API:

   cairo_surface_t *
   cairo_pdf_surface_create (cairo_write_func_t    write_func,
                             cairo_destroy_func_t  destroy_closure_func,
                             void                  *closure,
                             double                width_inches,
                             double                height_inches,
                             double                x_pixels_per_inch,
                             double                y_pixels_per_inch);

   typedef cairo_status_t (*cairo_write_func_t) (const void *data,
                                                 unsigned int length,
                                                 void *closure);
   typedef void (*cairo_destroy_func_t) (void *data);

The write_func is called whenever the backend needs to write data, and 
is passed a pointer to the data, the length of the data and the closure 
argument given to the surface constructor.  When the surface is finished 
eventually, the destroy_closure_func is called with the closure as its 
single argument, to free up resources allocated for the closure.

I've added this stdio convenience function:

   cairo_surface_t *
   cairo_pdf_surface_create_for_file (FILE         *fp,
                                      double       width_inches,
                                      double       height_inches,
                                      double       x_pixels_per_inch,
                                      double       y_pixels_per_inch);

and I added the finish function to the API:

   /**
    * cairo_surface_finish:
    * @surface: the #cairo_surface_t to finish
    *
    * This function finishes the surface and drops all references to
    * external resources.  For example, for the Xlib backend it means
    * that cairo will no longer access the drawable, which can be freed.
    * After calling cairo_surface_finish() the only valid operations on a
    * surface are getting and setting user data and referencing and
    * destroying it.  Further drawing the the surface will not affect the
    * surface but set the surface status to
    * CAIRO_STATUS_SURFACE_FINISHED.
    *
    * When the last call to cairo_surface_destroy() decreases the
    * reference count to zero, cairo will call cairo_surface_finish() if
    * it hasn't been called already, before freeing the resources
    * associated with the surface.
    *
    * Return value: CAIRO_STATUS_SUCCESS if the surface was finished
    * successfully, otherwise CAIRO_STATUS_NO_MEMORY or
    * CAIRO_STATUS_WRITE_ERROR.
    **/
   cairo_status_t
   cairo_surface_finish (cairo_surface_t *surface);

As indicated from the documentation, I've also added two new error 
codes: CAIRO_STATUS_SURFACE_FINISHED which is set if the user tries to 
draw to a closed surface, and CAIRO_STATUS_WRITE_ERROR, which is set if 
a backend fails to write to an output stream.  "Write error" may seem a 
bit too generic, but I don't like the idea of exposing a large number of 
IO error codes either.  The API in this patch should be flexible enough 
though: if you want a simple, easy to use API, use the convenience 
functions (similar to the situation with the toy font API). On the other 
hand, if you care about the specifics of the write failure, use the 
callback API and record the error details in the implementation of the 
write callback.

There is also a convenience function:

   void
   cairo_finish (cairo_t *cr);

which just calls cairo_surface_finish() on the target surface for the 
cairo_t.

In the backend API, I've renamed the destroy surface function to finish. 
  The way it works is that the finish function is required to clean up 
the backend specific parts of the surface, but in contrast to the 
destroy function it doesn't free the memory allocated for the surface. 
After finish has been called for a given surface, the backend is 
guaranteed that it will never see that surface again.

cheers,
Kristian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: output-stream.patch
Type: text/x-patch
Size: 69984 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20050221/f2339807/output-stream.bin


More information about the cairo mailing list