[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