[cairo] darken everything except ..

Carl Worth cworth at cworth.org
Thu May 1 13:14:27 PDT 2008

On Thu, 1 May 2008 21:33:17 +0200, "Rene Sansman" wrote:
> Hi Cairo developers, and thank you for a very good and easy-to-use library.

Hi Rene,

We're happy to hear that you're having fin with cairo!

I'm especially happy to hear people say that they find it easy to
use. That's been an important goal of cairo from the beginning.

> I have a bunch of polygons that the user can click on. Now I want to
> "disable" some of them, and I want to indicate this by making them darker.
> The easiest way seems to be to draw a dark semi-transparent gray rectangle
> over everything else, and mask out the enabled polygons.

Sure. So you'll want a translucent gray source pattern to paint with,
which you can arrange with:

	cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.5);

You can use any value for alpha of course---it doesn't have to be 0.5.
And you can also use whatever color you'd like as well too.

> But I cant figure out how to do the masking (how to cut holes in the
> rectangle).

You said "rectangle". But there's no reason you need to draw a
rectangle and "cut holes in it". Instead, simply create a path
for each of the polygons you want to disable. Something like:

foreach polygon P:
	cairo_new_sub_path (cr);
	foreach vertex V in P:
		cairo_line_to (cr, V.x, V.y);
	cairo_close_path (cr);

Then you draw exactly that shape with:

cairo_fill (cr);

My code for creating the path for the polygons takes advantage of a
little trick that cairo_line_to gets turned into cairo_move_to at the
beginning of a new sub path. Without that trick you might do something

foreach polygon P:
	foreach vertex V in P:
		if (V is first vertex)
			cairo_move_to (cr, V.x, V.y);
			cairo_line_to (cr, V.x, V.y);
	cairo_close_path (cr);

> cant use a pattern for masking here, so that leaves me with having to create
> a new surface the size of the original surface, and use that as the mask. I
> havent tried this, but wouldnt it waste a lot of memory? I'm uncomfortable
> with duplicating everything, but then again I dont really know what a
> surface is inside of Cairo, so maybe I'm imagining problems here.

There's no need to create a new surface that I can see, (unless I'm
really misunderstanding what you are trying to do). But if you ever do
need to do that, the push/pop_group API can make it easy to create a
new mask, (where it takes care of creating the intermediate surface
for you):

	cairo_pattern_t *mask;

	cairo_push_group_with_content (cr, CAIRO_CONTENT_ALPHA);
	/* Draw the contents of your mask here. */
	mask = cairo_pop_group (cr);
	cairo_mask (cr, mask); /* Use the mask */

I hope that helps. Do let us know if you have further questions.

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

More information about the cairo mailing list