[ 
https://issues.apache.org/jira/browse/FOP-3358?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Martin Leitner updated FOP-3358:
--------------------------------
    Description: 
When a PDF page that uses patterns is embedded with fop-pdf-images and form 
XObjects are *not* enabled (the default), each pattern object is written into 
the output PDF more than once under the same object number.
h3. Steps to reproduce

Attached {{test.fo}} places {{shading.pdf}} (the file from fop-pdf-images' own 
{{{}test/resources{}}}) twice on one page:
{code:java}
fop -fo test.fo -pdf out.pdf
{code}
Then count the object headers in {{{}out.pdf{}}}, e.g. {{{}grep -a -c "^22 0 
obj" out.pdf{}}}.
h3. Actual result (FOP 2.11 + fop-pdf-images 2.11 from Maven Central, PDFBox 
3.0.3)
 * Two {{{}external-graphics of shading.pdf{}}}: objects 22 and 23 (the two 
patterns) are each written {*}4 times{*}.
 * With only one {{{}external-graphic{}}}: objects 22 and 23 are each written 
{*}twice{*}.

The same happens with 2.10 and on current {{main}} (7dc1190).
h3. Expected result

Each indirect object is written exactly once. An object number/generation pair 
identifies one indirect object (ISO 32000-1, 7.3.10); repeating it makes the 
file body inconsistent with the cross-reference table.
h3. Cause

{{PDFCloner.cacheClonedObject}} already registers every cloned indirect object, 
patterns included, via {{PDFDocument.registerObject}} (object number + output 
queue). {{PatternUtil.promotePatterns()}} then calls {{setObjectNumber}} + 
{{addObject}} on *every* entry of the target page's {{/Pattern}} dictionary, so 
those patterns go into the output queue a second time.

That dictionary also accumulates across {{createStreamFromPDFBoxPage}} calls 
for the same target page, so every further embedded image re-queues the 
patterns of all earlier ones as well. This is why the count grows with the 
number of images on a page.

With form XObjects enabled, {{PatternUtil}} is constructed disabled and the 
problem does not occur.

We noticed it because our FOP build refuses to write a stream that has already 
been written, which turns this into "java.io.IOException: Stream is closed". 
Stock FOP silently writes the duplicates.
h3. Fix

Attached {{FOP-pdf-images-promotePatterns.patch}} (against {{main}} 7dc1190): 
{{promotePatterns()}} skips patterns that already have an object number, 
because they are already in the output queue, either from the cloner or from an 
earlier call for the same page. Direct (unnumbered) pattern dictionaries are 
promoted as before.

The patch adds two tests to {{{}PDFBoxAdapterTestCase{}}}:
 * {{testPatternsAreWrittenOnce}} - one embedded page, with and without form 
XObjects
 * {{testPatternsOfTwoImagesOnOnePageAreWrittenOnce}} - two embedded pages on 
one target page

Both tests fail on {{main}} without the change (objects written 2x, and 3x/2x 
in the two-image case) and pass with it. The full fop-pdf-images test suite 
passes: 117 tests.

  was:
When a PDF page that uses patterns is embedded with fop-pdf-images and form 
XObjects are *not* enabled (the default), each pattern object is written into 
the output PDF more than once under the same object number.

h3. Steps to reproduce

Attached {{test.fo}} places {{shading.pdf}} (the file from fop-pdf-images' own 
{{test/resources}}) twice on one page:

{code}
fop -fo test.fo -pdf out.pdf
{code}

Then count the object headers in {{out.pdf}}, e.g. {{grep -a -c "^22 0 obj" 
out.pdf}}.

h3. Actual result (FOP 2.11 + fop-pdf-images 2.11 from Maven Central, PDFBox 
3.0.3)

* Two {{external-graphic}}s of {{shading.pdf}}: objects 22 and 23 (the two 
patterns) are each written *4 times*.
* With only one {{external-graphic}}: objects 22 and 23 are each written 
*twice*.

The same happens with 2.10 and on current {{main}} (7dc1190).

h3. Expected result

Each indirect object is written exactly once. An object number/generation pair 
identifies one indirect object (ISO 32000-1, 7.3.10); repeating it makes the 
file body inconsistent with the cross-reference table.

h3. Cause

{{PDFCloner.cacheClonedObject}} already registers every cloned indirect object, 
patterns included, via {{PDFDocument.registerObject}} (object number + output 
queue). {{PatternUtil.promotePatterns()}} then calls {{setObjectNumber}} + 
{{addObject}} on *every* entry of the target page's {{/Pattern}} dictionary, so 
those patterns go into the output queue a second time.

That dictionary also accumulates across {{createStreamFromPDFBoxPage}} calls 
for the same target page, so every further embedded image re-queues the 
patterns of all earlier ones as well. This is why the count grows with the 
number of images on a page.

With form XObjects enabled, {{PatternUtil}} is constructed disabled and the 
problem does not occur.

We noticed it because our FOP build refuses to write a stream that has already 
been written, which turns this into "java.io.IOException: Stream is closed". 
Stock FOP silently writes the duplicates.

h3. Fix

Attached {{FOP-pdf-images-promotePatterns.patch}} (against {{main}} 7dc1190): 
{{promotePatterns()}} skips patterns that already have an object number, 
because they are already in the output queue, either from the cloner or from an 
earlier call for the same page. Direct (unnumbered) pattern dictionaries are 
promoted as before.

The patch adds two tests to {{PDFBoxAdapterTestCase}}:
* {{testPatternsAreWrittenOnce}} - one embedded page, with and without form 
XObjects
* {{testPatternsOfTwoImagesOnOnePageAreWrittenOnce}} - two embedded pages on 
one target page

Both tests fail on {{main}} without the change (objects written 2x, and 3x/2x 
in the two-image case) and pass with it. The full fop-pdf-images test suite 
passes: 117 tests.


> PDF Images: PatternUtil.promotePatterns writes pattern objects of an embedded 
> PDF page more than once
> -----------------------------------------------------------------------------------------------------
>
>                 Key: FOP-3358
>                 URL: https://issues.apache.org/jira/browse/FOP-3358
>             Project: FOP
>          Issue Type: Bug
>          Components: renderer/pdf
>    Affects Versions: 2.10, 2.11, main
>            Reporter: Martin Leitner
>            Priority: Major
>         Attachments: FOP-pdf-images-promotePatterns.patch, out.pdf, 
> shading.pdf, test.fo
>
>
> When a PDF page that uses patterns is embedded with fop-pdf-images and form 
> XObjects are *not* enabled (the default), each pattern object is written into 
> the output PDF more than once under the same object number.
> h3. Steps to reproduce
> Attached {{test.fo}} places {{shading.pdf}} (the file from fop-pdf-images' 
> own {{{}test/resources{}}}) twice on one page:
> {code:java}
> fop -fo test.fo -pdf out.pdf
> {code}
> Then count the object headers in {{{}out.pdf{}}}, e.g. {{{}grep -a -c "^22 0 
> obj" out.pdf{}}}.
> h3. Actual result (FOP 2.11 + fop-pdf-images 2.11 from Maven Central, PDFBox 
> 3.0.3)
>  * Two {{{}external-graphics of shading.pdf{}}}: objects 22 and 23 (the two 
> patterns) are each written {*}4 times{*}.
>  * With only one {{{}external-graphic{}}}: objects 22 and 23 are each written 
> {*}twice{*}.
> The same happens with 2.10 and on current {{main}} (7dc1190).
> h3. Expected result
> Each indirect object is written exactly once. An object number/generation 
> pair identifies one indirect object (ISO 32000-1, 7.3.10); repeating it makes 
> the file body inconsistent with the cross-reference table.
> h3. Cause
> {{PDFCloner.cacheClonedObject}} already registers every cloned indirect 
> object, patterns included, via {{PDFDocument.registerObject}} (object number 
> + output queue). {{PatternUtil.promotePatterns()}} then calls 
> {{setObjectNumber}} + {{addObject}} on *every* entry of the target page's 
> {{/Pattern}} dictionary, so those patterns go into the output queue a second 
> time.
> That dictionary also accumulates across {{createStreamFromPDFBoxPage}} calls 
> for the same target page, so every further embedded image re-queues the 
> patterns of all earlier ones as well. This is why the count grows with the 
> number of images on a page.
> With form XObjects enabled, {{PatternUtil}} is constructed disabled and the 
> problem does not occur.
> We noticed it because our FOP build refuses to write a stream that has 
> already been written, which turns this into "java.io.IOException: Stream is 
> closed". Stock FOP silently writes the duplicates.
> h3. Fix
> Attached {{FOP-pdf-images-promotePatterns.patch}} (against {{main}} 7dc1190): 
> {{promotePatterns()}} skips patterns that already have an object number, 
> because they are already in the output queue, either from the cloner or from 
> an earlier call for the same page. Direct (unnumbered) pattern dictionaries 
> are promoted as before.
> The patch adds two tests to {{{}PDFBoxAdapterTestCase{}}}:
>  * {{testPatternsAreWrittenOnce}} - one embedded page, with and without form 
> XObjects
>  * {{testPatternsOfTwoImagesOnOnePageAreWrittenOnce}} - two embedded pages on 
> one target page
> Both tests fail on {{main}} without the change (objects written 2x, and 3x/2x 
> in the two-image case) and pass with it. The full fop-pdf-images test suite 
> passes: 117 tests.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to