[cairo] Alpha masks

Carl Worth cworth at redhat.com
Wed Jan 5 14:07:11 PST 2005


On Sun, 05 Sep 2004 14:53:03 -0400, Owen Taylor wrote:
> I was trying to figure out how with Cairo to do the following
> simple operation:
>  
>  Given a single channel (A8) surface, draw a solid color
>  with the surface as the mask.

Yes, this is clearly a desirable operation.

> What I came up with was:

[a painful exercise with temporary pattern and surface objects]

> Which more or less works (I think there are some bugs in the cairo_gstate_show_surface()
> transform fun), but feels clumsy to me, and not particularly natural either. Why is the 
> pattern being used as the *mask*? The prototypical pattern doesn't have a alpha
> channel at all.

You got farther than I expected. I was under the impression that we
hadn't yet exposed an interface for setting the mask for the composite
operation. Using pattern as mask is inconsistent as the pattern is
supposed to provide the source color, (and for show_surface the
surface provides the source color instead).

I had always expected we would want to add functions to set the
"current mask" in ways analogous to setting the current color. I
suppose that gives us:

	void
	cairo_set_mask_rgb_color (cairo_t *cr, double red, double green, double blue);

	void
	cairo_set_mask_alpha (cairo_t *cr, double alpha);

	void
	cairo_set_mask_pattern (cairo_t *cr, cairo_pattern_t *pattern);

And the current mask would affect all drawing operations.

This would simplify your example significantly, (less than half as
many calls, and one object instead of two):

	image_pattern = cairo_pattern_create_for_surface (image_surface);
	cairo_set_mask_pattern (cr, image_pattern);
	cairo_rectangle (cr, width, height);
	cairo_fill (cr);
	cairo_pattern_destroy (image_pattern);

This would also let us fix the inconsistency in the use of
cairo_set_alpha, (currently it affects both the solid source color as
well as a constant mask for show_surface).

> My expectation would be that showing a RGB or RGBA surface would ignore the pattern,
> showing a A-only surface would use the surface as a mask for the pattern. Does this
> make sense to other people?

That strikes me as inconsistent. But we could add another new function
to paint the current pattern/color through a mask surface. This would
be analogous to PostScript's imagemask operator. We could name it
cairo_show_surface_mask perhaps? or maybe cairo_show_mask_surface?

Then, your example could be simplified to:

	cairo_show_surface_mask (cr, image_surface, width, height);

which is starting to look quite reasonable.  (Oh, and I want to
eliminate the width/height arguments from show_surface already, in
which case we should drop them here as well).

The cairo_show_surface_mask function would simply be a new drawing
function, and would not have any side effect on the current mask.

There should be very little actual work to make all this work, since
currently the mask operand is sitting there mostly unused in the
backend interface.

If there aren't any big objections to the interface proposed above,
I'll give an implementation a shot.

-Carl




More information about the cairo mailing list