15.2 Implementation

Support for a new type of document writer requires a new structure, derived from fz_document_writer:

typedef struct 
{ 
   fz_document_writer_begin_page_fn *begin_page; 
   fz_document_writer_end_page_fn *end_page; 
   fz_document_writer_close_writer_fn *close_writer; 
   fz_document_writer_drop_writer_fn *drop_writer; 
   fz_device *dev; 
} fz_document_writer;

For instance:

typedef struct 
{ 
   fz_document_writer super; 
   <foo specific fields> 
} foo_document_writer;

A generator function should be defined to return such an instance, perhaps:

fz_document_writer *fz_new_foo_document_writer(fz_context *ctx, const char *path, <foo specific params>) { 
   foo_document_writer *foo = fz_new_derived_document_writer(ctx, foo_document_writer, foo_begin_page, foo_end_page, foo_close, foo_drop); 
 
   <initialise foo specific fields> 
 
   return &foo->super; 
}

This uses a friendly macro that allocates a structure of the required size, initialises the function pointers as required, and zeroes the extra values in the structure.

/* 
   fz_new_document_writer_of_size: Internal function to allocate a 
   block for a derived document_writer structure, with the base 
   structures function pointers populated correctly, and the extra 
   space zero initialised. 
*/ 
fz_document_writer *fz_new_document_writer_of_size(fz_context *ctx, size_t size, fz_document_writer_begin_page_fn *begin_page, 
   fz_document_writer_end_page_fn *end_page, fz_document_writer_close_writer_fn *close, fz_document_writer_drop_writer_fn *drop); 
 
#define fz_new_derived_document_writer(CTX,TYPE,BEGIN_PAGE,END_PAGE,CLOSE,DROP) \ 
   ((TYPE *)Memento_label(fz_new_document_writer_of_size(CTX,sizeof(TYPE),BEGIN_PAGE,END_PAGE,CLOSE,DROP),#TYPE))

The actual work for the document writer is done in the functions that are passed to fz_new_derived_document_writer. In the example above these were foo_begin_page, foo_end_page, foo_close, and foo_drop. These have the following 4 types respectively.

/* 
   fz_document_writer_begin_page_fn: Function type to start 
   the process of writing a page to a document. 
 
   mediabox: page size rectangle in points. 
 
   Returns a fz_device to write page contents to. 
*/ 
typedef fz_device *(fz_document_writer_begin_page_fn)(fz_context *ctx, fz_document_writer *wri, const fz_rect *mediabox); 
 
/* 
   fz_document_writer_end_page_fn: Function type to end the 
   process of writing a page to a document. 
 
   dev: The device created by the begin_page function. 
*/ 
typedef void (fz_document_writer_end_page_fn)(fz_context *ctx, fz_document_writer *wri, fz_device *dev); 
 
/* 
   fz_document_writer_close_writer_fn: Function type to end 
   the process of writing pages to a document. 
 
   This writes any file level trailers required. After this 
   completes successfully the file is up to date and complete. 
*/ 
typedef void (fz_document_writer_close_writer_fn)(fz_context *ctx, fz_document_writer *wri); 
 
/* 
   fz_document_writer_drop_writer_fn: Function type to discard 
   an fz_document_writer. This may be called at any time during 
   the process to release all the resources owned by the writer. 
 
   Calling drop without having previously called close may leave 
   the file in an inconsistent state. 
*/ 
typedef void (fz_document_writer_drop_writer_fn)(fz_context *ctx, fz_document_writer *wri);

Once defined, if this is intended to be a generally useful document writer, it should probably be hooked into fz_new_document_writer, where it can be selected by appropriate format and options strings.