Bug 44002 - drawImage uses a too large area when in printing mode
Summary: drawImage uses a too large area when in printing mode
Status: RESOLVED FIXED
Alias: None
Product: poppler
Classification: Unclassified
Component: cairo backend (show other bugs)
Version: unspecified
Hardware: Other All
: medium normal
Assignee: poppler-bugs
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-12-21 01:46 UTC by Benjamin Berg
Modified: 2012-01-11 06:50 UTC (History)
0 users

See Also:
i915 platform:
i915 features:


Attachments
PDF file in question (561.28 KB, application/pdf)
2011-12-21 01:46 UTC, Benjamin Berg
Details
script I used to rendre the document (2.07 KB, application/octet-stream)
2011-12-21 01:48 UTC, Benjamin Berg
Details
Script that reproduces the error without poppler (1.53 KB, application/octet-stream)
2011-12-25 12:38 UTC, Benjamin Berg
Details
patch that fixes pdf creation (1.01 KB, patch)
2011-12-26 17:08 UTC, Benjamin Berg
Details | Splinter Review
patch to use cairo_paint (1.59 KB, patch)
2012-01-11 06:08 UTC, Adrian Johnson
Details | Splinter Review

Description Benjamin Berg 2011-12-21 01:46:19 UTC
Created attachment 54628 [details]
PDF file in question

OK, this is a weird bug, and I am kind of stuck trying to even figure out where it is (cairo/pixman/poppler).

What happens is, that the attached PDF file will only render at certain zoom/dpi values. You can see this in evince happening, when you open it and zoom in to 400% the image will disappear. What you do not see there is, that the images will appear again if you render it at an even larger scale of eg. 900dpi.

I am attaching the PDF in question, and a small script that I have been using to convert the PDF to TIFF images. (change the DPI in the script to eg. 100 or 900 to see the image appear).

The easiest workaround seems to be to use pdftoppm instead of trying to render the PNG myself. This seems to work around it by not using the cairo backend.
Comment 1 Benjamin Berg 2011-12-21 01:48:01 UTC
Created attachment 54629 [details]
script I used to rendre the document
Comment 2 Benjamin Berg 2011-12-25 12:35:28 UTC
Outch.

I found the problem (after looking through the cairo trace, stepping trough cairo, and finally trying to reproduce the problem with a simple script ...).

So, the trouble is, that the PDF will overflow cairo's 24.8 (1 sign bit) fixed point number representation.

It contains the following command:

0 4058686.144 2037628.645 -4058684.387 re W n

With the tranformation matrix at that point, this results in a rectangle between the points (in px):
(-1753.3703124604863, 3439.9252751940003) (-9657653340.689249, -3435427201.820131)

And some of these values are larger than 2^23.

I guess I should investigate how those insane numbers could creep into the PDF (and fix the affected PDFs). A workaround in Poppler (or cairo?) might be to clip the rather large numbers to something more sane. Which might not be easy because of the transformation matrix.

I'll attach the test script which reproduces the error.
Comment 3 Benjamin Berg 2011-12-25 12:38:23 UTC
Created attachment 54813 [details]
Script that reproduces the error without poppler
Comment 4 Benjamin Berg 2011-12-26 17:08:16 UTC
Created attachment 54837 [details] [review]
patch that fixes pdf creation

OK. So it is one thing that PDFs with insane clip regions are not rendered correctly (and I guess one can consider that to be OK).

Now the reason for the broken PDF however is also in poppler. The bug was introduced in commit d63293af (last two hunks), which causes a way to large rectangle to be used when drawing images in printing mode.
Comment 5 Benjamin Berg 2012-01-09 09:08:01 UTC
As the history of the comments seems to confuse people, here a go at a self contained explanation.

Short version (which hopefully should be enough):

Commit d63293af6 (Carlos Garcia Campos, Turn EXTEND_PAD off when printing) did the following change:
-  cairo_rectangle (cairo, 0., 0., 1., 1.);
+  if (printing)
+    cairo_rectangle (cairo, 0., 0., width, height);
+  else
+    cairo_rectangle (cairo, 0., 0., 1., 1.);

In the "printing" case, this results in a clip area that is very large (ie. dest_width * image_width, dest_height * image_height; where dest_width/dest_height is from the current transformation matrix).

So, just removing the special case will fix the problem. Another way to fix it would be to replace the "printing" case with a cairo_paint, as the extend mode is CAIRO_EXTEND_NONE for the "printing" case; this could be more in the spirit of the commit by Carlos.

----

Long version:

So as I understand it:
 1. In a PDF an image will always be drawn in the rectangle (0, 0, 1, 1), and the size is specified by changing the transformation matrix.
 2. Poppler transforms the patterns matrix, so that the image is mapped into this space. This happens in line 2765 and following:

>  cairo_matrix_init_translate (&matrix, 0, height);
>  cairo_matrix_scale (&matrix, image_width, -image_height);
>  cairo_pattern_set_matrix (pattern, &matrix);

 3. A draw_rectangle in the rectangle (0, 0, 1, 1) is done. (Line 2785)

Now, when poppler is in printing mode, the last point fails. Instead of drawing in the area (0, 0, 1, 1) it draws in the area (0, 0, image_width, image_height). This rectangle is then multiplied with the current transformation matrix (scaling it by ~595 and ~842 for a whole A4 page).

To be exact, look at the following output:
q
0 841.89 595 -841 re W n
q
0 4058686.144 2037628.645 -4058684.387 re W n
595.275678 0 0 840.133386 0 1.756407 cm
/a0 gs /x11 Do
Q
Q

The image has the size of 3423x4831 pixel. This is multiplied by the above matrix:
  3423 * 595.275678 = 2037628.645794
  4831 * 840.133386 = 4058684.387766

As one can see, this gives us the values from the way too large clip rectangle.


Once you have these huge numbers in a PDF, you can easily overflow cairo by rendering this at 300 DPI to an image surface. It means the clip region gets a size of:
  4058684.387766 pt * 300px / 72pt = 16911184.949025 px
Which is much larger than 2^23.
Comment 6 Adrian Johnson 2012-01-11 06:08:25 UTC
Created attachment 55431 [details] [review]
patch to use cairo_paint

Here's a patch to use cairo_paint when printing instead of the clip/fill.
Comment 7 Carlos Garcia Campos 2012-01-11 06:23:44 UTC
(In reply to comment #6)
> Created attachment 55431 [details] [review] [review]
> patch to use cairo_paint
> 
> Here's a patch to use cairo_paint when printing instead of the clip/fill.

Please push it. Thanks!, and thanks Benjamin for the detailed explanation :-)
Comment 8 Adrian Johnson 2012-01-11 06:50:56 UTC
Pushed.


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.