[cairo] Re: Filling and stroking an object with different color/alpha

Adam Jackson ajax at nwnk.net
Tue May 2 11:11:12 PDT 2006


On Monday 01 May 2006 20:42, Carl Worth wrote:
> If you compare PostScript and PDF you'll see that PostScript provides
> separate fill and stroke operations while PDF provides fill, stroke,
> and fill_and_stroke.
>
> We looked at both of those when designing cairo. The big problem that
> fill_and_stroke has is that you will of course want to do each with a
> different color. So, in PDF you end up with a stroking color and a
> non-stroking color, a stroking alpha and a non-stroking alpha
> etc. It ends up over-complicating the rendering model and the
> interfaces for only a modest benefit, in my view.
>
> For example, instead of set_source, set_source_rgb, set_source_rgba,
> and set_source_surface, we would have to have two variants of
> each. And then we'd have to carefully specify which of the two sources
> would be used by all the other operators besides fill and stroke,
> (paint, mask, show_glyphs, etc.) which wouldn't actually be
> obvious.
>
> So that seems like the wrong direction to me.

Just for reference, OpenVG can do fill and stroke in one step.  The 
fundamental color source type is called a VGPaint, which corresponds roughly 
to a Picture in Render now that we have solid and gradient pictures.  Paints 
can be solid, linear gradient, radial gradient, or pattern; you define their 
content by setting source color, gradient parameters, or image, as 
appropriate.

    extern VGfloat stroke_color[4];
    extern VGImage fill_image;

    VGPaint fill_paint = vgCreatePaint();
    VGPaint stroke_paint = vgCreatePaint();

    vgSetPaint(fill_paint, VG_FILL_PATH);
    vgSetPaint(stroke_paint, VG_STROKE_PATH);

    vgSetParameteri(fill_paint, VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN);
    vgPaintPattern(fill_paint, fill_image);
    vgSetParameteri(stroke_paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
    vgSetParameterfv(stroke_paint, VG_PAINT_COLOR, 4, stroke_color);
    // ...
    vgDrawPath(VG_FILL_PATH | VG_STROKE_PATH);

It is, of course, fully orthogonal; the stroke paint can be a pattern, etc.  
The important distinction, relative to cairo, is that it's a different answer 
to the zero-one-infinity rule.  Rather than only allowing one instance of 
paint state per context, paints are promoted to objects, you may have any 
number of them, and you bind them into the context as you need them.

Introducing this concept into cairo now while still preserving the push_group 
semantics would be a bit awkward.  I don't have a particular opinion on which 
style is better, but I think the claim that allowing fill_and_stroke as one 
operation necessarily complicates the API is a bit overstated.

Now, if you insist on a fully cairo-ish API, where arg 1 is always the cairo_t 
and there are minimal enum parameters, then yeah, it'd be a bit gross:

    cairo_set_paint_color(cr, fill_paint, fill_color);

Which is pretty wrong, paint state is not context state.  My opinion would be 
to drop the cairo_t and arg 1 should be the cairo_paint_t, but that's a 
pretty massive style change for cairo and should not be attempted.  Even if 
you did leave it like the above, you'd still have to choose between:

    cairo_set_paint(cr, fill_paint, CAIRO_FILL_PAINT); // alternative 1, enum
    cairo_set_fill_paint(cr, fill_paint); // alternative 2, many entrypoints

But then I actually like the GL API style, so I've probably already discounted 
myself from the discussion.

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


More information about the cairo mailing list