Bug 29463

Summary: Bézier curve is not rendered correctly
Product: cairo Reporter: Martin Horák <horakm>
Component: generalAssignee: Carl Worth <cworth>
Status: RESOLVED FIXED QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: normal    
Priority: medium    
Version: 1.8.0   
Hardware: All   
OS: All   
Whiteboard:
i915 platform: i915 features:
Attachments: Rendered output
Zoomed in, with nodes
Program to generate the zoomed image

Description Martin Horák 2010-08-09 10:31:34 UTC
Created attachment 37737 [details]
Rendered output

Below is a code snippet and the result is attached as png file.

cairo_new_sub_path( cr );
cairo_move_to( cr, 667.00, 287.75 );
cairo_curve_to( cr, 667.00, 270.50
		643.50, 253.75,
		643.75, 255.00 );
cairo_set_line_width( cr, 12.0 );
cairo_stroke( cr );
Comment 1 Martin Horák 2010-08-11 02:09:33 UTC
The wrong rendering also occurs under Linux, so I suppose it is not a platform specific issue
Comment 2 Andrea Canciani 2010-08-11 02:21:02 UTC
Created attachment 37785 [details]
Zoomed in, with nodes

(In reply to comment #1)
> The wrong rendering also occurs under Linux, so I suppose it is not a platform
> specific issue
The problem is in cairo stroking code, but it is also present in other libraries (quartz fails in a different way when stroking the same curve, but fails anyway).
In the attached image, the bezier nodes are red, green, blue, cyan. It can be seen that the bezier curve ends with the tangent directed downwards, but the stroker isn't able to get it correct, thus this seems to be a precision/accuracy problem in the stroker.
The (future, not yet working, expecially for degenerate cases) stroke-to-path code will hopefully be able to handle this situations.
Comment 3 Andrea Canciani 2010-08-11 02:22:04 UTC
Created attachment 37786 [details]
Program to generate the zoomed image
Comment 4 Martin Horák 2010-08-12 04:50:41 UTC
I briefly take a look at the code and it seems the problem in this specific case lies in incorrect decomposition of bézier curve into the separate (thick) line segments for stroking operation.

The implemented decomposition algorithm (widely used and robust Casteljau) focuses on finding points on a bézier curve. In each subdivision, the difference from curve to ideal zero-thick line segment is evaluated. If the line segment diference to curve falls below a tolerance threshold, the line segment is outputted as a curve approximation. In this sense, there is nothing wrong and I assume that for filling operations, the current implementation works perfectly.

However, when this decomposition (with the same error criteria) is used for stroking operation, it may miss some part of curve, where tangent is changed rapidly, although a curve approximation by an ideal line is almost perfect.

In my opinion, for fixing this issue, there is no need to change the stroker or
decomposition algorithm, but just update the error criteria to take into account
a tangent of two points on the curve (in case the decomposition itself serves as an input to the stroking operation).
Comment 5 Andrea Canciani 2010-09-10 00:33:40 UTC
1.10 produces output like https://bugs.freedesktop.org/attachment.cgi?id=37785
which is correct.
Please reopen if you can reproduce your problem with the new version.

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.