Background: I recently generated slides for a talk (originally SVG, then converted to PDF with librsvg+cairo), but they appeared as full-page, black smears when viewed with evince (poppler+cairo).
Diagnosis: I was able to trim down the failure to a single, small, gradient-filled rectangle. I'll attach an SVG version of the rectangle, which was written by hand and is trivial to verify as correct. I'll also attach a PDF version of the rectanlge. I haven't manually verified this as correct, but it does render correctly with acroread. Finally, I'll attach PNG files showing a correct rendering of the SVG file (from a librsvg-based svg2png), and the incorrect rendering by poppler of the PDF file, (from a poppler-based pdf2png).
Finally, I want to point out that the bakground of the -pdf2png.png file is coming out white, but in the evince (0.8.3) rendering of the PDF file, the output is black, (with some gray stripes).
Recommendation: It's likely time to bite the bullet and implement poppler gradients as cairo gradients, (at least when using the cairo backend). That would certainly be sufficient to make me happy, and should eliminate bugs like this.
Created attachment 14183 [details]
A simple, gradient-filled SVG file
Created attachment 14184 [details]
The buggy PDF file (converted from the svg with svg2pdf)
Created attachment 14185 [details]
A correct rendering of the rectangle (from the SVG with svg2png)
Created attachment 14186 [details]
The buggy rendering of the PDF file (with a poppler-based pdf2png)
One of the difficulties in implementing pdf gradients with cairo is how to deal with Postscript functions. For example axial gradients have a linearly varying parameter but the actual color values are expressed in terms of an arbitrary Postscript function. ie. the following is a valid axial gradient, r=sin(t), g=cos(t), b=0, where t varies linearly.
(In reply to comment #5)
> One of the difficulties in implementing pdf gradients with cairo is how to deal
> with Postscript functions. For example axial gradients have a linearly varying
> parameter but the actual color values are expressed in terms of an arbitrary
> Postscript function. ie. the following is a valid axial gradient, r=sin(t),
> g=cos(t), b=0, where t varies linearly.
Yeah, that could be tricky. One could punt and just call the existing code in a case like that, (meaning that many of these cases will still draw garbage, but hopefully the actual usage is rare). Or one could sample that function at various points in order to compute a static color-stop array suitable for passing to cairo.
If it can be an arbitrary function though, I suppose it doesn't give you any guarantees about how smooth it is so that you can know when you've sampled it enough?
Created attachment 14507 [details] [review]
Begin adding support for using cairo gradients to paint gradients.
Here's a lightly tested patch that does axial shading using cairo's linear gradients.
Jeff, please keep the list in CC if you assign yourself a bug.
(In reply to comment #7)
> Created an attachment (id=14507) [details]
> Begin adding support for using cairo gradients to paint gradients.
> Here's a lightly tested patch that does axial shading using cairo's linear
I made a start on this recently as well but never got any further than you have.
My plan for the stitching and exponential functions was to go over each function to get the boundary points and use these as gradient stops. If the exponential function has N=1 there is nothing further to do. If N!=1, bisect the stops until the color error is less than some predefined tolerance.
For Type 0 Sample functions, use each sample as a stop.
For the Type 4 Postscript functions, I was planning on sampling values at a number of points. I wanted to avoid anything like the existing code that bisects the sample points until the color difference is less than some tolerance. This has the flaw that the bisection stops when two almost identical colors are found even though the sample points may be widely spaced apart with further color changes between these points. Keeping the sampling interval small would give best results and should be ok for PS/PDF printing since we are using a linear gradient between stops rather the the solid color the existing code uses. Further optimization to reduce the number of stops can be done by checking if multiple consecutive sample values can be approximated with a linear gradient.
When shading->getExtend0() != shading->getExtend1() I was planning to add an extra stop top extend the gradient out to the bounding box on one side.
This bug is fixed since poppler 0.12.