pdfpdf.jsmupdfpdfium

A PDF with different outputs in different PDF viewers (with shades)


Consider the following PostScript file

[1 0 0.5 0.866 150 550] concat
<< 
   /ShadingType 2 
   /Coords [ 0 0 100 100] 
   /BBox [ 0 0 100 100] 
   /ColorSpace [ /DeviceRGB ] 
   /Function 
      << 
         /FunctionType 0 
         /Domain [0 1] 
         /Range [0 1 0 1 0 1] 
         /BitsPerSample 8 
         /Size [2] 
         /DataSource <FFA0A0FFE0E0> 
      >>
   /Extend [false false] 
>> 
shfill

Consider that we convert that file in PDF with GhostScript (ps2pdf) or Adobe Distiller.

The resulting PDF does not render the same way in the different PDF viewers :

Who is right?


Solution

  • In my opinion Adobe Acrobat is right but the specification could be read differently, too.

    Your PDF contains the following content stream:

    /GS1 gs
    q
    1 0 .5 .866 150 550 cm
    /Sh1 sh
    Q
    

    I.e. first the current transformation matrix is changed, it is sheared and squished a bit, and then the shading Sh1 is painted. That shading in turn is defined as

    <</BBox[0 0 100 100]/ColorSpace/DeviceRGB/Coords[0 0 100 100]/Function 15 0 R/ShadingType 2>>
    

    I.e. with a 100×100 square bounding box (interpreted as a temporary additional clipping path) and an axial shading along its (0, 0) to (100, 100) diagonal, matching your postscript definition.

    The shading operator sh is specified as

    Operands Operator Description
    name sh (PDF 1.3) Paint the shape and colour shading described by a shading dictionary, subject to the current clipping path. The current colour in the graphics state is neither used nor altered. The effect is different from that of painting a path using a shading pattern as the current colour. name is the name of a shading dictionary resource in the Shading subdictionary of the current resource dictionary (see 7.8.3, "Resource dictionaries"). All coordinates in the shading dictionary are interpreted relative to the current user space. (By contrast, when a shading dictionary is used in a Type 2 pattern, the coordinates are expressed in pattern space.) All colours are interpreted in the colour space identified by the shading dictionary’s ColorSpace entry (see "Table 77 — Entries common to all shading dictionaries"). The Background entry, if present, is ignored.
    This operator should be applied only to bounded or geometrically defined shadings. If applied to an unbounded shading, it paints the shading’s gradient fill across the entire clipping region, which may be time-consuming.

    (ISO 32000-2:2017, Table 76 — Shading operator)

    In particular: All coordinates in the shading dictionary are interpreted relative to the current user space.

    Thus, the square bounding box / temporary clip path is squished and sheared by the current transformation matrix to a non-rectangular parallelogram as can be viewed in Adobe Acrobat:

    Screenshot

    I mentioned above that the specification can be read differently, too: If one considers the BBox entry as the coordinates of two points, the lower left corner and the upper right corner of the box, and applied the transformation before making the result a box, one would get a squished, elongated rectangle as can be viewed in Chrome:

    Screenshot

    But the BBox here is specified as an array of four numbers giving the left, bottom, right, and top coordinates, respectively, of the shading’s bounding box (ibidem, Table 77 — Entries common to all shading dictionaries) and not as the coordinates of two endpoints of a diagonal. Thus, I'd favor the first interpretation also implemented by Adobe.

    I don't have a copy of ISO 32000-2:2020 yet, so maybe this has been clarified one way or the other.


    The situation would be different if the shading would have been used in a pattern which would have served as current color during a fill instruction. In that case the specification says:

    A pattern’s appearance is described with respect to its own internal coordinate system. Every pattern has a pattern matrix, a transformation matrix that maps the pattern’s internal coordinate system to the default coordinate system of the pattern’s parent content stream (the content stream in which the pattern is defined as a resource). The concatenation of the pattern matrix with that of the parent content stream establishes the pattern coordinate space, within which all graphics objects in the pattern shall be interpreted.

    (ISO 32000-2:2017, Section 8.7.2 — General properties of patterns)

    In this case the square bounding box with the diagonal axial shading would not have been subject to the current transformation matrix.