[cairo] Fuzzy lines

Carl Worth cworth at cworth.org
Mon Nov 6 11:50:23 PST 2006


On Mon, 06 Nov 2006 16:49:38 +1300, Piotr Zurek wrote:
> I just wanted to ask how do you usually approach the problem of
> pixel-aligned lines in your applications.

To avoid "fuzzy lines" the key is to just put all the geometry that
you want to be "sharp", (likely all straight horizontal and vertical
segments---but it turns out to also help for the extremal points of
curves as well), and integer locations on the device grid.

> What I tried to do is to test the current line width before the stroke
> for each path I draw. If the line width is an odd number I translate it
> by (0.5, 0.5) and after the stroke, I translate it back by (-0.5, -0.5).

That kind of thing, (translating by 0.5 before creating the path), can
work _if_ you know that all of the path data consists of integers.

> OK. Should I also check what the current point is before I create the
> path and see if the path is drawn at integer coordinates?

Here's one way to approach it. Let's assume we have an device-space
integer line and we want to snap all geometry to the device-pixel
grid.  CTM. Remembering that we want the geometry to land on integers,
that means we want the path coordinates to be either on integers (for
even line widths) or half-integers (for odd line widths). So, for each
coordinate (x,y) we can do:

	cairo_user_to_device (cr, &x, &y);
	if (odd_width) {
	    x = round (x + 0.5) - 0.5;
	    x = round (y + 0.5) - 0.5;
	} else {
	    x = round (x);
	    y = round (y);
	}
	cairo_device_to_user (cr, &x, &y);

And then pass the resulting (x,y) to the path-creation functions.

Here's some code I wrote once that does this kind of thing (as well as
snapping the line width itself):

http://webcvs.cairographics.org/cairo-demo/png/snapping.c?content-type=text%2Fplain&view=co

I even experimented with allowing this kind of thing in cairo itself,
but I wasn't very happy with the result. In general there's a problem
that "correct" snapping is often scene-dependent and global in nature
so cairo really isn't going to be able to achieve it.

But if users just avoided some imagined "snapping support" in cairo in
such a situation would it cause any problem? The other bad problem I
saw is that my snapping experiment destroyed a lot of fine details so
that scaling an SVG down a lot made it get really ugly, (where the
unsnapped version was quite lovely at all scales). That ugliness is
probably what most made me reject my experiment. It could be avoided
to some extent by not snapping for anything with fine features, but I
don't know how well we could make cairo do that, (other than line
width < 1.0 pixels say).

And the real risk with trying to do something "smart" there is making
cairo generate results that are ugly, but worse, doing it
unpredictably.

In some situations now, cairo is generating ugly results, (the fuzzy
lines), but its behavior is so easily explained and predictable, (just
draw with graph paper, put integers at the intersections and put your
geometry on the lines), that users actually have a hope of fixing any
ugliness they encounter.

So I'd be extremely wary of any proposed change to cairo that would
rob it of that kind of predictability.

-Carl
-------------- 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/20061106/8e2e6eda/attachment.pgp


More information about the cairo mailing list