Bug 9064 - Weird performance on printing weird rectangles
Summary: Weird performance on printing weird rectangles
Status: RESOLVED FIXED
Alias: None
Product: cairo
Classification: Unclassified
Component: win32 backend (show other bugs)
Version: 1.2.6
Hardware: x86 (IA32) Windows (All)
: high normal
Assignee: Owen Taylor
QA Contact: cairo-bugs mailing list
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-11-17 08:53 UTC by Yevgen Muntyan
Modified: 2008-01-11 20:52 UTC (History)
1 user (show)

See Also:
i915 platform:
i915 features:


Attachments
test case (1.31 KB, text/plain)
2006-11-17 08:56 UTC, Yevgen Muntyan
Details
test case binary (6.50 KB, application/octet-stream)
2006-11-17 08:57 UTC, Yevgen Muntyan
Details

Description Yevgen Muntyan 2006-11-17 08:53:20 UTC
Printing on win32 with gtk here: drawing rectangles with certain sizes is
incredibly slow and takes huge amount of memory - 2-4 minutes and more than 100
megs with attached test case.

The rectangle size in the test case is taken from real code which does 
    cairo_rectangle (cr, 0, 0,
                     gtk_print_context_get_width (context),
                     gtk_print_context_get_height (context));
it draws a page rectangle (just in case yuo wonder where I got those fancy numbers).

I tried nice numbers like 0, 0, 100, 100, they work fine.
Comment 1 Yevgen Muntyan 2006-11-17 08:56:37 UTC
Created attachment 7818 [details]
test case

It's a GTK program, you need GTK-2.10 to compile it. On unix, it would be
gcc `pkg-config --cflags --libs gtk+-2.0` print.c
Comment 2 Yevgen Muntyan 2006-11-17 08:57:07 UTC
Created attachment 7819 [details]
test case binary
Comment 3 Yevgen Muntyan 2006-11-17 09:07:18 UTC
Sorry, forgot about the main thing: what's the rule for printing lines? Should
coordinates be integers/half-integers or something? I do draw lines for header
and footer, and it wouldn't be nice to freeze user machine by that.
Comment 4 Carl Worth 2007-03-12 11:35:16 UTC
I'm not very familiar with the specifics of the win32 backend, but I did just take  a quick look. And it does appear that the current implementation of the win32 backend doesn't accept geometry for graphics very often.

For example, in the test program here, cairo will first look to see if the cairo-win32 backend has an implementation of the backend->stroke() function. But that entry point is NULL, (see the intialization of cairo_win32_surface_backend near the end of cairo-win32-surface.c, for example).

Next, cairo attempts to construct a region consisting of rectangles specified as integers to be filled. If it can successfully do this, then it will call into the win32 fill_rectangles() function, (which is not NULL). This may be what is happening when you test with small integer values to cairo_rectangle().

Finally, if that fails as well, (for example, cairo computes non-integers for the final region), then cairo will fall back to creating a giant image surface and pushing that to the backend through its composite() backend function. This may be what you are hitting with your test case.

Various fixes could be done for this problem. For example, simply changing the tolerance value away from something insanely high, (such as the default 0.1 device pixels), and adding code to attempt rounding if withing the current tolerance might let the existing fill_rectangles() path handle this case.

More interesting approaches could allow other geometry besides rectangles to be drawn without falling all the way back to images. For example, if the win32 backend can detect that it is targeting a high-resolution output device, (that is, a printer rather than a display device), then it might be able to use something native to implement stroke() directly without sacrificing output quality. But here, I'm totally guessing as I have no experience with the capabilities of the APIs that win32 backend calls into.

The best thing I can suggest is to mail the cairo mailing list and ask for what could be done to improve the win32 backend in some of these directions. Subscription (which is unfortunately required before posting) instructions are available here:

        http://cairographics.org/lists

Have fun with cairo,

-Carl

Comment 5 Adrian Johnson 2008-01-11 20:52:37 UTC
This is fixed by the new cairo_win32_printing_surface that is in the 1.5.x snapshots and will be in 1.6.

The cairo_win32_surface uses a lot of image fallbacks to produce the correct output as the GDI API doesn't support antialiasing or transparency. GDI calls are used for some functions such as text and rectangles on integer coordinates. The problem with using cairo_win32_surface for printing is that at printer resolutions of 600dpi or more the bitmap for a full page is hundreds of meg in size and not very printer friendly. Even worse is that operations involving transparency require reading back the destination bitmap. Many printer drivers do not support this capability so the output will be incorrect.

The new cairo_win32_printing_surface is designed to use always use GDI calls. At printer resolutions antialiasing is not required and the surface uses the same internal meta surface used by the PostScript backend for generating fallback images for unsupported operations so access to a destination bitmap is not required.


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.