Bug 29470

Summary: Gradient rendering is imprecise
Product: cairo Reporter: Krzysztof Kosiński <tweenk.pl>
Component: image backendAssignee: Carl Worth <cworth>
Status: RESOLVED FIXED QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: major    
Priority: medium CC: soren.sandmann
Version: 1.9.15   
Hardware: All   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:
Attachments: Misaligned gradient
Interesting artifacts
Aliased edge
misalignment test case
misalignment test case output

Description Krzysztof Kosiński 2010-08-09 17:20:22 UTC
Rendering of large linear gradients is very broken. Basically the handles do not align correctly with what is rendered. Attached are two screenshots from a Cairo port of Inkscape that show the problems (the full source is available by saying: bzr co lp:~tweenk/inkscape/gsoc-cairo).
Comment 1 Krzysztof Kosiński 2010-08-09 17:23:49 UTC
Created attachment 37749 [details]
Misaligned gradient

I created a rectangle that spans the entire A4 page and added extra stops near the endpoint. Here the misalignment is clearly visible. The two ellipses and explanatory text were added separately.
Comment 2 Krzysztof Kosiński 2010-08-09 17:26:23 UTC
Created attachment 37750 [details]
Interesting artifacts

This screenshot shows artifacts that are the result of the gradient being placed differently depending on the tile which is currently being rendered. At this window size, the tiles are narrow vertical stripes.
Comment 3 Krzysztof Kosiński 2010-08-09 17:29:07 UTC
Created attachment 37751 [details]
Aliased edge

When two stops coincide (which is frequently used in SVG to create sharp transitions), the edge between their colors is aliased.
Comment 4 Andrea Canciani 2010-08-10 00:13:31 UTC
Gradient aliasing is expected, as no supersampling is done in pixman (yet).
Test cases (linking just to cairo, if possible) or details of the conditions reproducing the other two problems would be appreciated
Comment 5 Krzysztof Kosiński 2010-08-10 05:39:54 UTC
Created attachment 37766 [details]
misalignment test case

Minimal test case. Compile with
gcc gradient.c -o gradient `pkg-config --cflags --libs cairo`
Run and look at the gradient.png file.
Comment 6 Krzysztof Kosiński 2010-08-10 05:44:59 UTC
Created attachment 37767 [details]
misalignment test case output

Output of the test case with Cairo 1.9.15. The red dots mark the position of gradient stops. In the top right corner, the rendering is fairly correct, though the lower dot is not exactly on the line that marks the 100% black boundary. In the bottom left corner, the rendered gradient is completely misaligned with its stops.
Comment 7 Andrea Canciani 2010-08-12 02:20:34 UTC
Two pixman branches fixing the rendering of linear gradients are available here:
http://cgit.freedesktop.org/~ranma42/pixman/log/?h=wip/linear-fixed
http://cgit.freedesktop.org/~ranma42/pixman/log/?h=wip/linear-float

Can you confirm that both fix your rendering issues?
If both work fine, I'm going to investigate their performance.
Comment 8 Krzysztof Kosiński 2010-08-12 12:54:45 UTC
(In reply to comment #7)
> Two pixman branches fixing the rendering of linear gradients are available
> here:
> http://cgit.freedesktop.org/~ranma42/pixman/log/?h=wip/linear-fixed
> http://cgit.freedesktop.org/~ranma42/pixman/log/?h=wip/linear-float

Both branches work correctly on the test case and in the Cairo port of Inkscape.

When the gradient has a transformation matrix with entries that exceed the range of 16.16 fixed point, the rendering is still wrong. That's a different problem though, so I'll file it separately.
Comment 9 Andrea Canciani 2010-10-21 03:09:25 UTC
(In reply to comment #8)
> (In reply to comment #7)
> > Two pixman branches fixing the rendering of linear gradients are available
> > here:
> > http://cgit.freedesktop.org/~ranma42/pixman/log/?h=wip/linear-fixed
> > http://cgit.freedesktop.org/~ranma42/pixman/log/?h=wip/linear-float
> 
> Both branches work correctly on the test case and in the Cairo port of
> Inkscape.

A set of changes based on those branch has recently been merged in pixman/master:

commit 1d4f2d71facd5f2bbce74fbe3407ccea6cf4bea1
Author: Andrea Canciani <ranma42@gmail.com>
Date:   Wed Aug 11 09:58:05 2010 +0200

    Improve precision of linear gradients
    
    Integer division (without keeping the remainder) can discard a lot
    of information. Doing the division maths in floating point (and
    paying attention to error propagation) allows to greatly improve
    the precision of linear gradients.

and

commit 9b72fd1b857494ea928795c89a4f827e56fe26d3
Author: Andrea Canciani <ranma42@gmail.com>
Date:   Mon Oct 18 22:21:52 2010 +0200

    Make classification consistent with rasterization
    
    Use the same computations to classify the gradient and to
    rasterize it.
    This improves the correctness of the classification by
    avoiding integer division.


> 
> When the gradient has a transformation matrix with entries that exceed the
> range of 16.16 fixed point, the rendering is still wrong. That's a different
> problem though, so I'll file it separately.

I can't find the bugreport. It would be very useful to also have a testcase and to also check if the same problem affects radial gradients.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.