[cairo] Stroke and Fill

Carl Worth cworth at east.isi.edu
Wed Sep 1 07:06:21 PDT 2004

On Tue, 31 Aug 2004 23:02:21 -0400, Jose O Gonzalez wrote:
> 	If one uses colors with some transparency, or some
> compositing operation such as "add" say, one may want to do this
> so that there's no overdrawing of the stroking and filling -- ie. one
> may want to do this without overlapping the stroke and fill regions.
> 	Does Cairo's path rendering semantics have support
> for this?  eg. if the context has stroke line-width set to a value > 0,
> will filling of the interior occur complementary to the corresponding
> stroke region?

Cairo does not provide a direct mechanism for this.

Like PostScript, it has independent stroke and fill operators, (although
PostScript doesn't have a similar problem since it has only opaque

PDF provides non-opaque paint and resolves this issue by providing
stroke, fill, and stroke-and-fill operators. I don't like this approach
as it then has independent operators set_stroke_color and

There is a not-too-difficult means of getting the desired effect with
cairo. The trick is to do the stroke and fill with opaque paint onto an
intermediate surface, and then use cairo_show_surface to composite that
intermediate result with the desired compositing operator.

One advantage to this approach is that it can be used for more general
effects than just overlapping stroke and fill. For example the following
image shows overlapping text, fill, and an image, all composited as a
single group:


That image was rendered by cairo through code in the libsvg-cairo
library. The relevant code is something like the following:

	intermediate_surface = cairo_surface_create_similar (cairo_current_target_surface (cr),
							    width, height);
	cairo_set_target_surface (cr, intermediate_surface);

	/* Draw all the overlapping objects here. */

	/* Set up the compositing desired for the group */
	cairo_set_alpha (cr, opacity);
	cairo_show_surface (cr, intermediate_surface,
		            width, height);

	cairo_surface_destroy (intermediate_surface);

This is a bit of work, and I've been mulling over making this easier
with cairo, (via some sort of push_group/pop_group_function). We even
had such a thing at one point in time. Providing that kind of support in
cairo would have a few benefits:

	1) The user wouldn't have to actually create/destroy the
           intermediate surface.

	2) The interface would not necessarily need the width/height of
           the intermediate surface, but could automatically deal with
           things as they were drawn.

	3) There would likely be a way to simplify the matrix
           handling. If you look at the actual code in libsvg-cairo,
           you'll see that I actually have to set an identity matrix
           just before calling cairo_show_surface. We could probably
           eliminate the need for this extra manipulation with direct
           group support in cairo.

Well, that was a long answer to a short question. But I hope it was helpful.


More information about the cairo mailing list