Bug 50985 - Block elements inside inline elements that cause a page break where the next page has a different IPD causes NullPointerException
Summary: Block elements inside inline elements that cause a page break where the next ...
Status: NEEDINFO
Alias: None
Product: Fop - Now in Jira
Classification: Unclassified
Component: page-master/layout (show other bugs)
Version: trunk
Hardware: PC Windows XP
: P3 normal
Target Milestone: ---
Assignee: fop-dev
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-03-28 07:10 UTC by coolkidd3
Modified: 2012-04-24 05:35 UTC (History)
1 user (show)



Attachments
This test checks two pages are created without a NullPointerException (2.67 KB, text/plain)
2011-03-28 07:13 UTC, coolkidd3
Details
This test checks two pages are created without a NullPointerException (3.09 KB, text/plain)
2011-03-30 13:37 UTC, coolkidd3
Details
Test case showing issues with IPD (3.18 KB, text/plain)
2011-04-03 12:16 UTC, coolkidd3
Details

Note You need to log in before you can comment on or make changes to this bug.
Description coolkidd3 2011-03-28 07:10:09 UTC
The attached test case creates the following NullPointerException:
 
java.lang.NullPointerException
        at org.apache.fop.layoutmgr.AbstractBreaker.getNextBlockListChangedIPD(AbstractBreaker.java:815)
        at org.apache.fop.layoutmgr.AbstractBreaker.doLayout(AbstractBreaker.java:428)
        at org.apache.fop.layoutmgr.PageBreaker.doLayout(PageBreaker.java:90)
        at org.apache.fop.layoutmgr.PageSequenceLayoutManager.activateLayout(PageSequenceLayoutManager.java:107)
        at org.apache.fop.area.AreaTreeHandler.endPageSequence(AreaTreeHandler.java:238)
        at org.apache.fop.fo.pagination.PageSequence.endOfNode(PageSequence.java:120)
        at org.apache.fop.fo.FOTreeBuilder$MainFOHandler.endElement(FOTreeBuilder.java:349)
        at org.apache.fop.fo.FOTreeBuilder.endElement(FOTreeBuilder.java:177)
        at org.apache.xalan.transformer.TransformerIdentityImpl.endElement(TransformerIdentityImpl.java:1101)
        at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source)
        at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown Source)
        at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
        at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
        at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
        at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
        at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
        at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
        at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:484)
        at embedding.ExampleFO2PDF.convertFO2PDF(ExampleFO2PDF.java:91)
        at embedding.ExampleFO2PDF.main(ExampleFO2PDF.java:143)
 
This error occurs on FOP 1.0 and the latest version from the TRUNK.
 
The error gets resolved if I remove the text "Page 2", convert the inline to a block or simply remove the left margin from the simple page master.

After looking into the code it appears that block elements that are inside inline elements that cause a page break where the next page has a different IPD is not supported. 

The getNextBlockListChangedIPD() function seems to be where it only looks at for block elements and as a result keeps looking for something it will never find (since the block is in an inline element).

Thanks
Comment 1 coolkidd3 2011-03-28 07:13:09 UTC
Created attachment 26804 [details]
This test checks two pages are created without a NullPointerException
Comment 2 Andreas L. Delmelle 2011-03-29 20:37:52 UTC
Right... and on my end, it works without issues. I have a strong suspicion that this is a duplicate of Bug #50574, for which I have the fix, but still need to commit.

*** This bug has been marked as a duplicate of bug 50574 ***
Comment 3 coolkidd3 2011-03-30 13:33:46 UTC
Unfortunately the patch for Bug #50574 doesn’t resolve the issue for me. Debugging the code shows that the lastRestartPosition variable is set to positionAtBreak at line 767 and never used again. This will be because there is only one page break in my test case.

The main issue seems to be that the positionAtBreak is set to the Second Block element which has been initiated as a LeafNode. This results in the getPosition function returning null and the subsequent getLM obviously fails thereafter on line 824.

My knowldge of FOP's layout manager is limited so I have no idea why the Second Block has been set to a leaf node when it clearly has children. 

Changing the Third Block from a self closing element to one that encapsulates the "Page 2" text resolves the issue e.g:. 
<fo:flow flow-name="xsl-region-body" id="Flow">
    <fo:block id="First_Block">Page 1</fo:block>
    <fo:block id="Second_Block">
        <fo:inline id="First_Inline">
            <fo:block id="Third_Block">Page 2</fo:block>
        </fo:inline>
    </fo:block>
</fo:flow>

This will be due to the positionAtBreak variable being set to the Flow element which does have children. 

Another example would be changing the first Inline element to a Block element:
<fo:page-sequence
    master-reference="chapter-master" master-name="chapter-master">
    <fo:flow flow-name="xsl-region-body" id="Flow">
        <fo:block id="First_Block">Page 1</fo:block>
        <fo:block id="Second_Block">
            <fo:block id="First_Inline">
                <fo:block id="Third_Block"/>Page 2
            </fo:block>
        </fo:block>
    </fo:flow>
</fo:page-sequence>

This sets the positionAtBreak variable to the newly changed block element which has no problem getting its child Block.

I am not sure if there is a problem with the logic behind the positionAtBreak variable e.g. should it be set to Flow instead of the Second Block? Or is it the initialisation of the Second Block without any children?

Any ideas?
Thanks
Comment 4 coolkidd3 2011-03-30 13:37:49 UTC
Created attachment 26818 [details]
This test checks two pages are created without a NullPointerException

Just updated the test case to include ID's on the Blocks and Inline elements so they are easier to refer to in both code and discussion.
Comment 5 Andreas L. Delmelle 2011-03-30 13:58:00 UTC
Aahh... OK, I think I see. Sorry, another local change on my end that is responsible. See also Bug #44328; the patch currently there may not immediately solve the problem, but I am going to post a new patch over there pretty soon.

If I am correct, by correcting widows/orphans control (default = 2 lines), the zero-height line generated by the empty block should always move to the next page with the following/last line. I already had a feeling that this was going to resolve some ambiguous situations. This might be proof...

In the meantime, until you get a chance to verify on your end, I'll keep this open.
Comment 6 coolkidd3 2011-03-30 15:24:37 UTC
Great, after applying the patch for Bug #44328; the PDF was created perfectly, will test it again after you submit your updated pathtch for Bug #44328; but for now my test case is working.

Thanks
Comment 7 Andreas L. Delmelle 2011-03-31 15:00:09 UTC
(In reply to comment #6)
> Great, after applying the patch for Bug #44328; the PDF was created perfectly,

Good news. You can also try the patch I just attached there.

I will keep this bug open nevertheless. I somehow have a feeling that it may just be a matter of finding the scenario that triggers this behavior again. All we have established so far, is that it works as long as there is no break-possibility between the empty block and the following text. 

If you feel like playing with the test case... :-) It could be as easy as just adding 2 lines before and after the empty block. Widows/orphans will only apply to those first and last lines, giving the algorithm a chance to break.
Comment 8 coolkidd3 2011-04-03 12:11:49 UTC
(In reply to comment #7)
> If you feel like playing with the test case... :-) It could be as easy as just
> adding 2 lines before and after the empty block. Widows/orphans will only apply
> to those first and last lines, giving the algorithm a chance to break.

Yes, it broke as soon I added an extra line before or after Page 2, and both cases gave the following error:

java.lang.UnsupportedOperationException: Don't know how to restart at positionnull
        at org.apache.fop.layoutmgr.AbstractBreaker.getNextBlockListChangedIPD(AbstractBreaker.java:754)
        at org.apache.fop.layoutmgr.AbstractBreaker.doLayout(AbstractBreaker.java:428)
        at org.apache.fop.layoutmgr.PageBreaker.doLayout(PageBreaker.java:90)
        at org.apache.fop.layoutmgr.PageSequenceLayoutManager.activateLayout(PageSequenceLayoutManager.java:107)
        at org.apache.fop.area.AreaTreeHandler.endPageSequence(AreaTreeHandler.java:244)
        at org.apache.fop.fo.pagination.PageSequence.endOfNode(PageSequence.java:120)
        at org.apache.fop.fo.FOTreeBuilder$MainFOHandler.endElement(FOTreeBuilder.java:349)
        at org.apache.fop.fo.FOTreeBuilder.endElement(FOTreeBuilder.java:177)

I will upload the updated test case which brings about this error
Comment 9 coolkidd3 2011-04-03 12:16:11 UTC
Created attachment 26847 [details]
Test case showing issues with IPD
Comment 10 coolkidd3 2011-04-03 12:20:52 UTC
Forgot to mention that this happens with the latest patch from Bug #44328;  (including attachements; id=26843, id=26845 and id=26846)
Comment 11 Andreas L. Delmelle 2011-04-03 14:20:03 UTC
(In reply to comment #9)
> Created an attachment (id=26847) [details]
> Test case showing issues with IPD

Did you also have the patch for 50574 applied? If I include that, it seems to trigger an infinite loop... :-/

What we have here, is a tricky corner case. A combination of changing IPD and at the same time, overflow in block-progression-direction. Something very similar --but obviously not identical- to bug 50574. What it shows, is that my proposed fix for 50574 is either not the right way to address this issue, or at least, is incomplete.

In an overflow situation at the very first break --in this case: after an IPD change-, the BreakingAlgorithm generates an auxiliary penalty at the start of the element list to allow shifting the content to the next column/page if possible. A new IPD change after page 2 results in an attempted restart from that auxiliary break-possibility.

With the attempted fix for 50574, this would trigger an infinite series of restarts, since we keep bumping into the overflow on every new page.
Comment 12 Glenn Adams 2012-04-01 21:16:42 UTC
what is the status of this bug? can it be moved to resolved?
Comment 13 Glenn Adams 2012-04-07 01:45:01 UTC
resetting P2 open bugs to P3 pending further review
Comment 14 Glenn Adams 2012-04-24 05:35:55 UTC
(In reply to comment #12)
> what is the status of this bug? can it be moved to resolved?

andreas?