[cairo] New query functions: cairo_current_path, cairo_current_path_flat

Carl Worth cworth at east.isi.edu
Tue Feb 17 19:25:27 PST 2004

I've just committed two new functions to cairo to allow the user to
query the current path: cairo_current_path and cairo_current_path_flat
(prototypes below).

The behavior of cairo_current_path may be familiar to users of the
PostScript operator "pathforall". It accepts 4 callback functions for
move_to, line_to, curve_to, and close_path along with a void *
argument to be passed to each callback. The function iterates over the
current path, calling the callbacks.

This is the first time that I've added a callback-based interface to
cairo, and I'm proceeding cautiously as it may impact issues related
to reentrancy, locking, etc. I think things should work fine as the
implementation is careful to copy all needed data out of the cairo_t
and onto the stack before calling any of the callbacks. This means
that it is legal to call into cairo from within any of the
callbacks. It also means that any modifications made to the current
path within the callbacks will not affect the data passed to the
callbacks --- cairo_current_path will only iterate over the path as it
was at the time of the initial call, (this is similar to the
PostScript semantics for pathforall).

The second function, cairo_current_path_flat, allows the user to query
a piecewise linear approximation of the current path. It is similar to
cairo_current_path except that it does not accept a curve_to
callback. Instead, any curved portions of the path will be converted
to line segments, (within the limits of the current tolerance value),
and the line_to callback will be called as necessary.

This behavior is roughly the same as the combination of the two
PostScript operators flattenpath and pathforall. I chose this
approach, as I never liked the implications of a "flattenpath"
operator. The sequence of flattenpath/stroke can result in a contour
that deviates by more than the current tolerance from the correct
result obtained by a call to stroke. I decided not to allow an
operator that would "corrupt" the path data within cairo in this
way. This way a user can only get the ugly result by directly storing
the poor approximation of the path via calls to cairo_line_to.

As usual, any feedback on these new functions would be welcome.


typedef void (cairo_move_to_func_t) (void *closure,
                                     double x, double y);

typedef void (cairo_line_to_func_t) (void *closure,
                                     double x, double y);

typedef void (cairo_curve_to_func_t) (void *closure,
                                      double x1, double y1,
                                      double x2, double y2,
                                      double x3, double y3);

typedef void (cairo_close_path_func_t) (void *closure);

extern void
cairo_current_path (cairo_t                     *cr,
	            cairo_move_to_func_t        *move_to,
	            cairo_line_to_func_t        *line_to,
	            cairo_curve_to_func_t       *curve_to,
	            cairo_close_path_func_t     *close_path,
	            void                        *closure);

extern void
cairo_current_path_flat (cairo_t                        *cr,
	                 cairo_move_to_func_t           *move_to,
	                 cairo_line_to_func_t           *line_to,
	                 cairo_close_path_func_t        *close_path,
	                 void                           *closure);

More information about the cairo mailing list