]> git.cworth.org Git - cworth.org/blob - src/cairo/a_chain_of_bugs.mdwn
Fix broken link
[cworth.org] / src / cairo / a_chain_of_bugs.mdwn
1 [[!meta title="A chain of bugs"]]
2
3 [[!tag cairo]]
4
5 With cairo's recent 1.6.4 release, we've hoped to reach the nirvana of
6 applications that display and print documents with perfect
7 fidelity. Unfortunately, reality isn't always as pleasant as we would
8 like. I recently received a bug report that Firefox 3 (using cairo
9 1.6.4) resulted in a blurry mess when printing a very simple web page,
10 (some text, a table, and an image). Exploring the details of this case
11 reveals at least three independent problems that conspire to give the
12 bad results.
13
14 ## Bug 1: Firefox+cairo uses image fallbacks for table borders
15
16 First, here's the simplest web page I was able to construct to show
17 the problem, (nothing more than a single-cell table with a border):
18 [[bug.html]] (122 bytes).
19
20 Using Firefox3 with cairo 1.6.4 on a Fedora9 system, I did a "print to
21 file" and obtained the following PDF output: [[bug.pdf]] (14,465
22 bytes).
23
24 This output is still quite accurate and fairly usable. But we've
25 already seen problem #1. Note that the file size has increased by a
26 factor of 100 compared to the original HTML. The PDF does have more
27 content, (firefox adds a header and footer for example), but nothing
28 that explains such a large file. Instead, something about the way that
29 firefox is expressing the table border is resulting in cairo putting
30 fallback images into the resulting PDF file. So that's the first
31 bug. I'll look closer at this, (probably with libcairowrap), and make
32 a bug report to the mozilla folks if necessary.
33
34 Also, note that when cairo puts the fallback images into the PDF file
35 it uses a "knockout group" to do so. This is a particular PDF
36 construct that I'll discuss later.
37
38 ## Bug 2: Poppler+cairo expands knockout groups to full-page fallbacks
39
40 Next, we can use the poppler library, (with evince or a pdf2ps
41 utility), to read the PDF file and use cairo to generate a PostScript
42 file: [[bug.ps]] (138,067 bytes).
43
44 Notice that there has been another factor of 10 increase in the file
45 size. Here, poppler has convinced cairo to generate a full-page
46 fallback image rather than just the minimal fallback images present in
47 the PDF file. This is due to the way poppler is handling the knockout
48 group and really comes down to the difficulty of getting a single,
49 desired result to pass through two systems with very different
50 rendering models.
51
52 To explain a bit, (but ignoring many gory details), a PDF knockout
53 group can be a very complicated thing, so poppler has some fairly
54 sophisticated code to handle these. This support involves rendering
55 everything in the group twice and then using cairo's `DEST_OUT` and `ADD`
56 compositing operators to properly combine them. Well, PostScript can't
57 do fancy compositing like `DEST_OUT` and `ADD`, so of course cairo falls
58 back to image-based rendering for things. The irony here is that the
59 only reason cairo is using a knockout group in the original PDF file
60 is to _prevent_ any compositing from happening, (the fallback image
61 needs to replace any "native" content that might appear below it). And
62 it turns out that painting an image without any compositing is the
63 _only_ kind of image painting that PostScript knows how to do.
64
65 So, cairo is using an advanced feature of PDF to describe precisely the
66 semantic that PostScript supports natively. The change we need is to
67 fix poppler to recognize this case and ask for the simple thing from
68 cairo's PostScript backend so that we don't get this full-page fallback
69 explosion.
70
71 ## Bug 3: Cairo uses the wrong resolution for fallback images (in groups)
72
73 If it were only for those first two bugs, the intermediate file sizes
74 would have been larger than normal, but the final result would have
75 looked great and printed just fine. And in that case, I probably would
76 have never even received a bug report.
77
78 But there's a third problem that is the most pernicious, because it
79 results in the final result looking just awful. When cairo inserts the
80 full-page fallback into the final PostScript file, it is inserting it
81 at 300dpi, but it does that only after rendering it to an intermediate
82 72dpi image, which is then scaled up. That's why the final PostScript
83 file appears so blurry and hard to read.
84
85 This third problem is the first I attempted to fix, (since it involves
86 cairo alone), and I described my attempts in several posts to the cairo
87 mailing list over the past couple of days, beginning here:
88
89 [Bug with fallback resolution of
90 groups](http://lists.cairographics.org/archives/cairo/2008-May/014169.html)
91
92 In that series of posts I coded a minimal test case in cairo's test
93 suite for the resolution problem, and a patch that fixes that test
94 case. But when I use a patched cairo for the PDF to PostScript
95 conversion of the file described here, I end up with the following
96 result: [[bug-patched-cairo.ps]].
97
98 Here, there's still a giant, full-page fallback image, (this is
99 expected since I haven't touched poppler yet). And the image is at
100 least rendered at the correct resolution this time, (notice that the
101 text that appears is much more sharp than in the previous PostScript
102 file). However, the original HTML table is now entirely missing. So
103 there's definitely something wrong with my patch.
104
105 I'll continue to chase these bugs down. The interesting thing about
106 this chain is that it's only as strong as its weakest link. Fixing any
107 of the individual problems here will make the end-to-end behavior be
108 quite acceptable.
109
110 And I'll continue my quest to get high-quality display and print
111 output from cairo-using applications. It can be a challenging goal,
112 but it's also a lot of fun and very rewarding. Please feel free to
113 jump in and help if you're interested.