[cairo] API Shakeup: cairo_fill_preserve, cairo_stroke_preserve, cairo_clip_preserve

Carl Worth cworth at cworth.org
Tue Feb 15 22:07:45 PST 2005


As has recently been discussed, it would be quite convenient to be
able to write functions that can append to the current path. Things
like:

void
logo_path (cairo_t *cr)
{
    cairo_save (cr);

    /* Muck with CTM, and draw logo here. */

    cairo_restore (cr);
}

With the current implementation, a function written as above will not
work as the logo path will be destroyed at the call to cairo_restore.
To avoid this, the function can be re-written without
cairo_save/restore, but then it's a pain to write as the user must
manually save and restore the CTM, (and use a local variable for
this).

There has been a good proposal to solve this problem by moving the
path out of the graphics state, (eg. it will not be affected by
cairo_save/restore). The problem with this approach is that it would
break the (admittedly awkward) idiom for filling/stroking the same
path:

cairo_save (cr);
/* set source for fill */
cairo_fill (cr);
cairo_restore (cr);

/* set source for stroke */
cairo_stroke (cr);

We propose to address this problem by introducing two new variants of
cairo_fill and cairo_stroke that do not consume the current path:

	/* Like cairo_fill, but preserve the path after the fill. */
	void
	cairo_fill_preserve (cairo_t *cr);

	/* Like cairo_stroke, but preserve the path after the stroke. */
	void
	cairo_stroke_preserve (cairo_t *cr);

We do this by adding two new drawing operations rather than changing
the behavior of cairo_fill/stroke to always preserve in order to avoid
having to call cairo_new_path in the common case after most calls to
cairo_fill/stroke.

With this new API, the fill-then-stroke idiom becomes:

/* set source for fill */
cairo_fill_preserve (cr);

/* set source for stroke */
cairo_stroke (cr);

which I think we can all agree is much cleaner.

Also, this approach provides a great opportunity for eliminating
another source of confusion from the API. Currently, cairo_clip does
not consume the path, (since if it did, wrapping it in
cairo_save/restore to prevent this would make the call to cairo_clip
do nothing).

Instead, we can make cairo_clip consume the path, and also add:

	/* Like cairo_clip, but preserve the path after the clip. */
	void
	cairo_clip_preserve (cairo_t *cr);

Which provides nice consistency, and allows us to avoid having to add
a phrase to the documentation such as "this can cause unexpected
behavior" like the PostScript manual has when describing the
non-path-consumption behavior of the clip operator.

-Carl

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20050216/21adaadd/attachment.pgp


More information about the cairo mailing list