[cairo] API Shakeup: cairo_begin_group, cairo_end_group, cairo_get_group

Owen Taylor otaylor at redhat.com
Thu Jun 23 10:57:51 PDT 2005


On Thu, 2005-06-16 at 13:18 -0700, Carl Worth wrote:

> Here are the names I came up with for the current patch:
> 
> 	void
> 	cairo_begin_pattern (cairo_t *cr);
> 
> 	void
> 	cairo_begin_pattern_with_format (cairo_t *cr, cairo_format_t format);
> 
> 	cairo_pattern_t *
> 	cairo_end_pattern (cairo_t *cr);
> 
> 	void
> 	cairo_end_pattern_to_source (cairo_t *cr);
> 
> There reason I changed from "group" to "pattern" is that we are
> returning a cairo_pattern_t. Using the name "pattern" in the function
> names avoids the user having to learn an additional concept.

I'm not sold on this name change ... to me, the fact that it returns
a pattern is almost an implementation detail. A pattern is just how
we represent a drawing source, so of course this set of commands
returns a pattern, but as a concept, I think it's something other
than a pattern and deserves a distinct name.

We're not just creating a pattern: we're creating a pattern with
a set of drawing commands.

If someone had a problem that was best solved with this functionality,
you couldn't just say "Oh, you need to use a pattern" for that,
you'd need to say "Oh, you need to use begin/end pattern for that".
Introducing the name "group" for this doesn't seem inappropriate
to me.

> But this might be up for discussion to some extent, (see below).
> 
> I've ported a couple of tests and demos to use this new API. See
> test/mask in the patch below which is now quite a bit simpler and
> easier to read[*]. I also ported cairo-demo/X11/cairo-knockout.c (see
> separate patch) which also improved considerably.
> 
> [*] One exception is that the old code used the x/y parameters to
> cairo_mask_surface to place things in the right place, but the new
> code has to declare a local cairo_matrix_t and call
> cairo_matrix_init_identity, cairo_matrix_translate, and
> cairo_pattern_set_matrix to get the same effect with
> cairo_mask. There's obviously some missing convenience here, but I'm
> not sure exactly where.

Well, I would think that the natural thing to do would be to just
draw the mask x/y (which you could do with cairo_translate(),
say), and let the group code worry about creating a 

The change to main loop in test/mask.c isn't actually right: the
code is actually counting on the restriction to the temporary surface,
using begin_pattern will overwrite the entire output surface if
the size is automatically determined. (I'm not sure that
introducing begin_pattern() in this place is a good idea at all, because
it makes the whole thing much less a test of the specific functionality
of cairo_mask())

> One of the things I noticed is that there are at least three fairly
> distinct ways that this API might be commonly used:
> 
> 1) Intermediate compositing. That is, rendering several objects
>    together with some compositing operator, then compositing the
>    result as a whole onto the destination.
> 
> 2) Repeating pattern construction. Using cairo to draw to a pattern
>    that is then used as a repeating source.
> 
> 3) Mask construction. Using cairo to draw to a pattern that is then
>    used as a mask.
> 
> The test/mask.c code has one instance each of (1) and (3) while
> cairo-knockout has (1) several times and (2) once. The new
> test/begin_pattern.c code does (2).
> 
> The name "pattern" in the API works well for uses (2) and (3), but
> "group" does seem a better fit for use (1).

I don't have any problem with using the name "group" for a set of
drawing commands that repeat. Especially if we are straying towards
making groups not just a convenience function for creating surface
patterns...

> Then, there's an interesting problem that shows up here. For all of
> the uses, but most particularly for (1) it's very convenient that the
> API does not require the user to provide a size for the intermediate
> surface, (since conceptually the user doesn't even have to be aware
> that any intermediate surface is present). (And I should mention that
> the current patch does the simplest and least efficient thing by just
> creating an intermediate surface that is the same size as the target).
> 
> However, for use (2) a size is _required_ in order for the code to
> know when the pattern should start repeating. A similar problem will
> show up when we add meta surfaces to the API. A repeating pattern
> created from an unsized meta surface will need to know the repeat
> size. So I think what we want here is to add a new cairo_pattern
> function to set the repeat size rather than adding any size to the
> begin_pattern API. Something like:
> 
> 	void
> 	cairo_pattern_set_repeat_size (cairo_pattern_t *pattern,
> 				       double width, double height);

double width, double height here implies that you are doing programmatic
patterns - that repeating consists of redrawing the pattern multiple
times: repeating surface patterns need integer pixel repeats in
pattern space. 

Which raises various other questions:

 - Do you clip to the area? (0, 0, width, height)
 - What about having a cell that starts somewhere other than 0,0?
 - Do the X and Y repeats have to be the same as width and height?
 - What determines the coordinate system in which the width and
   height are interpreted? The coordinate system at begin_pattern()
   time?

   (this presumably is "pattern space" - but in the group API
   as originally conceived, pattern space is not an exposed concept: 
   at least until you try to set the matrix of a pattern created
   through the API.)

Regards,
						Owen
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
Url : http://lists.freedesktop.org/archives/cairo/attachments/20050623/2d7f09d5/attachment.pgp


More information about the cairo mailing list