23.7 Walking

Given a path, it can be useful to be able to read it out again. MuPDF uses this internally in a output devices such as the PDF or SVG devices (see subsection 9.5.4 PDF Output Device or subsection 9.5.6 SVG Output Device) to convert paths to a new representation, and in the draw device (see subsection 9.5.2 Draw Device) for rendering.

To isolate callers from the implementation specifics of paths, MuPDF offers a mechanism to ‘walk’ a fz_path, getting a callback for each command in the path.

typedef struct 
{ 
   /* Compulsory ones */ 
   void (*moveto)(fz_context *ctx, void *arg, float x, float y); 
   void (*lineto)(fz_context *ctx, void *arg, float x, float y); 
   void (*curveto)(fz_context *ctx, void *arg, float x1, float y1, float x2, float y2, float x3, float y3); 
   void (*closepath)(fz_context *ctx, void *arg); 
   /* Optional ones */ 
   void (*quadto)(fz_context *ctx, void *arg, float x1, float y1, float x2, float y2); 
   void (*curvetov)(fz_context *ctx, void *arg, float x2, float y2, float x3, float y3); 
   void (*curvetoy)(fz_context *ctx, void *arg, float x1, float y1, float x3, float y3); 
   void (*rectto)(fz_context *ctx, void *arg, float x1, float y1, float x2, float y2); 
} fz_path_walker; 
 
/* 
   fz_walk_path: Walk the segments of a path, calling the 
   appropriate callback function from a given set for each 
   segment of the path. 
 
   path: The path to walk. 
 
   walker: The set of callback functions to use. The first 
   4 callback pointers in the set must be non-NULL. The 
   subsequent ones can either be supplied, or can be left 
   as NULL, in which case the top 4 functions will be 
   called as appropriate to simulate them. 
 
   arg: An opaque argument passed in to each callback. 
 
   Exceptions will only be thrown if the underlying callback 
   functions throw them. 
*/ 
void fz_walk_path(fz_context *ctx, const fz_path *path, const fz_path_walker *walker, void *arg);

This function is called by giving a pointer to a structure containing callback functions, one for each type of path segment type. The function will walk the path structure and call the appropriate function pointer for each segment of the path in turn.

Callers of this function should not rely on getting exactly the same sequence of path segments out as was used to construct the path; the internal representation may have been optimised to an equivalent form on construction, and this will be reflected in the callbacks received. The path passed back will however be entirely identical (modulo possible infinitesimal rounding issues).

For example, MuPDF is capable of spotting that a cubic or quadratic bezier is actually a line; in such cases it may represent it as a line internally, saving memory and processing power.

Not all path consumers can cope with the full range of segment types that MuPDF natively supports, so some of the callback entries may be left blank (i.e. set to NULL). Rather than calling such an entry, MuPDF will decompose the path segment into one of the more basic types.

For example, if a path contains a quadratic segment and the quadto callback entry is NULL, MuPDF will automatically decompose it to a bezier segment and call the curveto entry instead.