Jason Harrop created FOP-3354:
---------------------------------

             Summary: NoSuchElementException in LMiter.next when a side float's 
end falls inside a table
                 Key: FOP-3354
                 URL: https://issues.apache.org/jira/browse/FOP-3354
             Project: FOP
          Issue Type: Bug
          Components: layout/page
    Affects Versions: main, 2.11
            Reporter: Jason Harrop


When a side float outlasts the paragraph it is anchored in and the content 
beside it continues into an fo:table, the float's end falls between two rows. 
PageBreaker.handleFloatLayout then reads the element list again from that break 
(FlowLayoutManager.getNextKnuthElements with a restart position inside the 
table). TableLayoutManager cannot be restarted (isRestartable() is false, as 
AbstractBreaker.containsNonRestartableLM checks for the IPD-change restart); 
the generic restart in BlockStackingLayoutManager.getNextKnuthElements asks 
setCurrentChildLM for the table's child layout manager, and the table's child 
iterator, already exhausted, throws:

{noformat}
java.util.NoSuchElementException
    at org.apache.fop.layoutmgr.LMiter.next(LMiter.java:69)
    at org.apache.fop.layoutmgr.LMiter.next(LMiter.java:27)
    at 
org.apache.fop.layoutmgr.AbstractLayoutManager.setCurrentChildLM(AbstractLayoutManager.java:132)
    at 
org.apache.fop.layoutmgr.BlockStackingLayoutManager.getNextKnuthElements(BlockStackingLayoutManager.java:278)
    at 
org.apache.fop.layoutmgr.FlowLayoutManager.getNextChildElements(FlowLayoutManager.java:225)
    at 
org.apache.fop.layoutmgr.FlowLayoutManager.addChildElements(FlowLayoutManager.java:148)
    at 
org.apache.fop.layoutmgr.FlowLayoutManager.getNextKnuthElements(FlowLayoutManager.java:121)
    at 
org.apache.fop.layoutmgr.PageBreaker.getNextKnuthElements(PageBreaker.java:270)
    at 
org.apache.fop.layoutmgr.AbstractBreaker.getNextBlockList(AbstractBreaker.java:723)
    at 
org.apache.fop.layoutmgr.PageBreaker.getNextBlockList(PageBreaker.java:179)
    at 
org.apache.fop.layoutmgr.PageBreaker.handleFloatLayout(PageBreaker.java:822)
{noformat}

No output is produced. Minimal FO (A4, 72pt margins, Times 12pt):

{noformat}
<fo:block line-height="14pt" space-after="10pt"><fo:float 
float="right"><fo:block line-height="40pt"
  padding-start="200pt">BOX</fo:block></fo:float>Heading</fo:block>
<fo:table table-layout="fixed" width="200pt" 
border-collapse="collapse"><fo:table-column column-width="200pt"/>
  <fo:table-body>five of: <fo:table-row><fo:table-cell border="0.5pt 
solid"><fo:block>cell N</fo:block>
  </fo:table-cell></fo:table-row></fo:table-body></fo:table>
<fo:block>after</fo:block>
{noformat}

The 40pt float outlasts the heading's 14pt line and its 10pt space, so its end 
falls after the second row. clear="both" on the table makes no difference.

*Fix (pull request to follow)*

PageBreakingAlgorithm.considerLegalBreak: a legal break between two boxes of 
the same layout manager that cannot be restarted is not taken as the float's 
edge; the edge waits for the first legal break after it. The rows below the 
float keep the table's width, which the table set once for all its rows, so 
nothing is drawn differently from a re-layout at the row, and the block after 
the table is laid out at full width.

Measured on main with the change: the FO above lays out, five rows at the 
table's width, "after" at full width below the table. Layout engine test 
float_edge-inside-table.xml, which threw before. The fop-core suite passes 
(3679 tests) and checkstyle is clean.



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

Reply via email to