[cairo] Non-antialiased rendering in image surface
Bill Spitzak
spitzak at gmail.com
Sat Jun 26 18:36:53 PDT 2010
On 06/26/2010 01:31 PM, cu wrote:
> I'll try to get a trace, but the issue is so common I don't think
> specific trace is needed. Essentially any polygon drawn using non-pixel
> aligned and non-axis-aligned edges causes this issue. All you need is
> two polygons that share a portion of their outline, draw one and fill,
> draw the other and fill. It's most visible when colors are the same.
>
> Attached is the image of two polygons sharing part of outline drawn with
> antialiasing turned on. Same area with antialiasing turned off looks
> like a square of plain uniform color, so I didn't bother attaching it -
> there is nothing there to see.
The problem is that "turn off antialiasing" is NOT the solution. This
may solve the internal lines, but the outer edge of the polygon ends up
aliased, and all the other lines look bad.
Anti aliasing by drawing a much higher resolution aliased image and then
filtering it down (often called supersampling? multisampling?) would
produce nice antialiased output without these artifacts. I think there
are Cairo back ends that do exactly that, and the (even theoretical)
existence of this solution shows that "turn off antialiasing" is not the
right approach.
The official supported Cairo solution is to use a temporary image
surface and composite using "SATURATE" and then composite the result
atop the image.
An idea I had, but I'm not sure it would work, is to add bracketing
calls to indicate that you are attempting exactly that:
cairo_start_filled_mesh();
draw polygons...;
cairo_end_filled_mesh();
The default behavior of these calls is to start a temporary surface and
set the function to SATURATE, and then end the temporary surface, put
the function back, and draw it.
Backends that do not have antialiasing problems can just ignore these calls.
Or it could be implemented in a different way, perhaps with an extra
temporary alpha channel that shows the coverage of the current mesh. Or
make a higher-resolution aliased temporary surface.
Another idea I had is a flag you can set to say that a particular edge
should be aliased. This would be set by the program on edges that it
knows adjoin another polygon. I don't like this as much as it makes
assumptions about the implementation, and the program would have to
determine if the adjacent polygons are actually on opposite sides of the
line (rather than overlapping each other).
Drawing surfaces in Cairo could also really use the ability to set the
color at each vertex. The results for polygons with more than 3 points
can be undefined (ie the triangulation is back-end dependent). This
would also allow strokes to vary their color along their length, the
need to do this is currently keeping me using OpenGL rather than Cairo
for graphics.
It would also be really useful to set the UV of the vertex from the
source image, to do texture mapping. However you will also have to set a
'W' value so that the source texture position is U/W,V/W when U,V,W are
linearly interpolated, that is the only way to get a correct 3-D
projection. If that is not done users will have to divide flat 3D
objects up into many thin triangles (this is also what they have to do
today if they want to use Cairo to draw such images).
More information about the cairo
mailing list