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 structure’s 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.