[cairo] group/pattern API

Vladimir Vukicevic vladimirv at gmail.com
Mon Dec 5 17:23:32 PST 2005


On 12/2/05, Carl Worth <cworth at cworth.org> wrote:
> On Sat, 12 Nov 2005 20:48:42 -0800, Vladimir Vukicevic wrote:

> > I suggest that we add distinct support for groups and patterns, with a
> > group being composited into the parent surface with the current
> > compositing operator and an alpha parameter to end_group (much like
> > cairo_paint_with_alpha()):
> >
> > void cairo_begin_group (cairo_t *cr);
> > void cairo_end_group (cairo_t *cr, double alpha);
>
> A _long_ time ago we had an API very much like this in cairo, (see the
> long commented-out cairo_push_group and cairo_pop_group in cairo.h).
> The reason this got pulled out was that the entanglement of the "end
> group" operation along with the "paint the group" operation caused
> confusion with regard to what graphics state is in place at the time
> of the implicit paint. (This was particularly confusing as
> cairo_pop_group also had an implicit cairo_restore in it).
>
> My latest proposal to return a cairo_pattern_t* from cairo_end_group
> is precisely intended to resolve this problem by separating the
> painting operation from the "end group" operation.
>
> > groups should nest; you should be able to begin_group as many times as
> > you'd like.
>
> Absolutely. Does returning a cairo_pattern_t* rather than implicitly
> painting cause any problem here?

My problem with pop/end returning a pattern is that I don't think that
the pattern is useful for anything else other than immediately calling
paint() with.  The only other API that I could find that has a similar
operation is Quartz, with CGContextBeginTransparencyLayer and
CGContextEndTransparencyLayer.  The docs state: "After a call to
CGContextEndTransparencyLayer, the result is composited into the
context using the global alpha and shadow state of the context. This
operation respects the clipping region of the context."

I guess if it's easier for it to just return a pattern, then sure,
I'll change my patch to do that.  That pattern just won't be much use
for anything else, though.  The other option is to allow the current
graphics compositing operator to apply to the end_group (e.g. within
the group, right before the end_group_call) to avoid the need to
specify it early on

Does it make sense to set a surface device offset while in the group,
and then right before returning the cairo_pattern_t* to set the
offsets back to 0,0, and instead set an appropriate matrix on the
pattern?

> > For patterns, I'd like to suggest a different interface -- I don't
> > think use cases (2) and (3) have much to do with the current cairo_t,
> > other than determining the surface type to use.  So, I suggest
> > something like this:
> >
> > cairo_t *cairo_pattern_begin (cairo_surface_t *reference_surface);
> > cairo_pattern_t *cairo_pattern_end (cairo_t *pattern_cairo);
>
> I don't like this. So far, we've been talking about creating a new
> kind of magic pattern named a "group", (which happens to have its
> create function split into begin/end_group rather than "group_create",
> but that's the best we've come up with).

Ah, I missed that dicussion.  I'd suggest not splitting create, and
instead having:

cairo_pattern_t *cairo_pattern_create_group (cairo_surface_t
*reference, int width, int height);
cairo_t *cairo_group_pattern_get_cairo (cairo_pattern_t *group_pattern);

The pattern surface would be initialized to some defined state, and
would be valid for rendering at any time.  You could pull out a
cairo_t at any time to perform additional rendering to the pattern.

How's that sound?  I think that we can do the group pattern creation
stuff in a separate patch from the context group API, though.

   - Vlad


More information about the cairo mailing list