[cairo] Transparent pattern may be wrong

David Reveman davidr at novell.com
Sun Feb 27 15:25:39 PST 2005


On Fri, 2005-02-25 at 12:31 -0800, Bill Spitzak wrote: 
> In an anti-aliased system such as Cairo specifying patterns as having 
> transparent edges may be the wrong thing to do. The problem is 
> double-premultiply:
> 
> It would be very common for a user to draw a rectangle exactly the same 
> size as the area of their source image. However if the transformation is 
> such that the rectangle does not land on pixel boundaries, the edge 
> pixels will be antialiased and thus the pattern pixels will be 
> multiplied by this antialias value. But the pattern itself is also 
> filtered, so if the edge is transparent, the pixel will already be 
> multiplied by the fraction that is inside. Thus it will be multiplied by 
> the coverage twice, producing a black border around the rectangle. The 
> effect is subtle but can get really annoying fast. This is especially 
> bad if various other errors cause the rectangle to not exactly line up 
> with the image edge.

We need to specify what EXTEND_TRANSPARENT means for surfaces without an
alpha channel.

surface         pixels              extend-transparent-pixel
RGBA          (r, g, b, a)         (0, 0, 0, 0)
A                 (0, 0, 0, a)        (0, 0, 0, 0)
RGB            (r, g, b, 1)         (0, 0, 0, ?)

It could either be:
1. (0, 0, 0, 1)
or
2. (0, 0, 0, 0)

If we want to be able to accelerate it with OpenGL, then it would have
to be option 1. And yes, I can imagine that this black border you
mentioned above could then be quite annoying and EXTEND_NEAREST as
default is probably a good idea.

If we specify it as option 2. Then this black border around rectangles
will always be a transparent black border and maybe not as annoying.

> I do not think an operation with such unexpected side effects should be 
> the default. In fact the only operations without unexpected effects is 
> nearest-pixel and a "mirror" repeat of the image. I recommend 
> nearest-pixel be the default. This also has the convient effect of being 
> the expected value for gradients.

Nearest-pixel for gradients would definitely be the best default. How do
we feel about having different default extend types for surfaces and
gradients?

This default extend type issue is really hard. Right now, I think I'm
for EXTEND_NEAREST. But I wouldn't be surprised if I changed my mind
tomorrow again.

> 
> There is no need to support transparent edge. The transparent edge can 
> be exactly emulated by making the pattern be 1 pixel larger on all 
> sides, with a border of transparent pixels, and using nearest-pixel for 
> the outside. Hardware mipmap implementation of transparent edge *has* to 
> do this anyway, so it may be more efficient to move this up to the Cairo 
> API because the pattern can be loaded directly into the texture.

I definitely don't think we should move this up to the API. Most
hardware can do transparent border and we don't want applications to
bother with 1 pixel border stuff. Glitz, which actually knows what the
hardware can do, handles this border emulation if necessary.

>  
> Transparent edge can also be emulated for most operators by making a 
> clip region of the proper rectangle.

Not for convolution filters and such. Not for transform+bilinear filter
with smooth edges.

-David




More information about the cairo mailing list