Bug 20091

Summary: Polygon clipping to surface fails for large coordinate values, limitations of the API not documented.
Product: cairo Reporter: cu <cairouser>
Component: generalAssignee: Carl Worth <cworth>
Status: RESOLVED MOVED QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: major    
Priority: high CC: cmantunes, peter.seefried
Version: 1.8.6   
Hardware: x86 (IA32)   
OS: All   
Whiteboard:
i915 platform: i915 features:
Attachments: Test case
Output example.
Same bug on Windows

Description cu 2009-02-12 16:18:38 UTC
The following code demonstrates the problem on my OS X 10.5 (using either freshly compiled cairo 1.8.6 or the one that installs from Mac ports)

When the program is ran with input values of 40000000 (40 million) for either of the dimensions, the surface is not filled completely. Instead only a narrow vertical bar is filled. Surface may not be filled at all if origin is moved (see commented code).

This prevents drawing of any polygons that have sufficiently large dimensions, and must be drawn into smaller "tiles" for example.
Comment 1 cu 2009-02-12 16:45:50 UTC
Created attachment 22876 [details]
Test case

Test case showing the problem. Run with parameters 100 40000000 (or 100000000 to be sure :) )
Comment 2 cu 2009-02-12 16:49:54 UTC
Created attachment 22878 [details]
Output example.

This is a sample of bad output. Parameters used were: 100 40000000

Also, verified that the bug is not present on Windows (XP, 32 bit)
Comment 3 cu 2009-02-12 19:09:08 UTC
Created attachment 22882 [details]
Same bug on Windows

I was able to reproduce the same problem on Windows. It only occurs with some large coordinates (see numbers in the example). After example runs, test.png is empty. 

If value of Y is selected symmetrically (i.e. -49M and +49M), the surface is properly filled (with red in this case).
Comment 4 cu 2009-02-12 19:17:24 UTC
Comment on attachment 22882 [details]
Same bug on Windows

#include <stdlib.h>
#include <stdio.h>
#include <cairo.h>


int main(int ac, char **av)
{
   double x1, y1;
   cairo_surface_t   *surf;
   cairo_t *cr;
         

   surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1000, 500);

   cr = cairo_create(surf);



   //cairo_surface_set_device_offset(surf, (-1. * x1 / 2.), y1 / 2.);
   //cairo_surface_set_device_offset(surf, 1000., 500.);

   cairo_new_path(cr);
   cairo_move_to(cr, 1000, -49000000);
   cairo_line_to(cr,  1000, 40000000);
   cairo_line_to(cr, -1000, 40000000);
   cairo_line_to(cr, -1000, -49000000);
   cairo_close_path(cr);
   cairo_set_source_rgb(cr, 1., 0., 0.);
   cairo_fill(cr);

   cairo_destroy(cr);

   cairo_surface_write_to_png(surf, "test.png");
   cairo_surface_destroy(surf);

   
   return 0;
}
Comment 5 M Joonas Pihlaja 2009-02-13 02:13:26 UTC
Hi,

I'm sorry I didn't have my brain switched on while looking at your test case earlier so completely missed the obvious problem: The input coordinates overflow cairo's internal fixed point numbers used to represent polygon geometry, and the resulting overflowed coordinates aren't to be trusted anymore.  The current format uses 24 bits to address the pixel and eight bits to address fractions of a pixel, leaving the valid coordinate range in the +-8M range.  This is up from the +32k range we had earlier, but obviously not the full double precision range.  So this is an expected failure after all. :|

I'm leaving this bug report open as a reminder until we prominently document the input coordinate restrictions and fail in a meaningful way in the face of large numbers.
Comment 6 Carlos Antunes 2014-09-25 23:55:34 UTC
Is this restriction on the max value for coordinates still in place? I am developing a Gerber viewer and was hoping that I could use the big integer numbers normally associated with Gerber files, without having to do any rescaling. Thanks!
Comment 7 Peter Seefried 2015-09-20 17:15:57 UTC
I experience some crap drawing with much smaller numbers when doing..

cairo_move_to (cr, x1, y1 );
cairo_line_to (cr, x2, y2 );

with
 x1=700,457386   y1=478,073704   x2=39032,412069   y2=141,069173

Probably cairo does some internal computation, and maybe some of the values there exceed the limit.

As a workaround, some clipping code before calling cairo_bla should work. But..

degree_of_reliance--;
Comment 8 Stefan 2017-11-08 22:07:08 UTC
I found the same problem, this (undocumented) limitation on the coordinate system severely limits the usability of the library for 'serious projects' like CAD software. In-memory surfaces (like the ones created with cairo_image_surface_create) have limitations on the coordinate system *well* below the claimed (and already limited) 24.8 bit fixed point space. 
For example, the following:
   cairo_move_to(ctx, -200000., -200000.);
   cairo_line_to(ctx, 200000., 200000.);
   cairo_stroke(ctx); 
clearly crossing the clip area will not be displayed.
Since in-memory surfaces are used for double buffering this limits the overall manageable space, even if user coordinates for screen surfaces can go (maybe?) up to +/- 8Mpixels.

It was really frustrating to discover that a 2D api with double precision coordinates is internally restricted to 20.something bits.


degree_of_reliance/=10;
Comment 9 GitLab Migration User 2018-08-25 13:53:37 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/cairo/cairo/issues/252.

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.