Summary: | Polygon clipping to surface fails for large coordinate values, limitations of the API not documented. | ||
---|---|---|---|
Product: | cairo | Reporter: | cu <cairouser> |
Component: | general | Assignee: | 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
Created attachment 22876 [details]
Test case
Test case showing the problem. Run with parameters 100 40000000 (or 100000000 to be sure :) )
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)
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 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;
}
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. 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! 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--; 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; -- 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.